feat(xo-server): remove legacy backups (#5735)

BREAKING: all `backup.*` API methods removed
This commit is contained in:
Julien Fontanet 2021-04-23 09:40:46 +02:00 committed by GitHub
parent 53038a0372
commit bdb0ca836c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 3 additions and 1441 deletions

View File

@ -53,7 +53,6 @@
"@xen-orchestra/xapi": "^0.6.1",
"ajv": "^8.0.3",
"app-conf": "^0.9.0",
"archiver": "^5.0.0",
"async-iterator-to-stream": "^1.0.1",
"base64url": "^3.0.0",
"bind-property-descriptor": "^1.0.0",
@ -108,7 +107,6 @@
"ndjson": "^2.0.0",
"openpgp": "^4.10.4",
"otplib": "^11.0.0",
"parse-pairs": "^1.0.0",
"partial-stream": "0.0.0",
"passport": "^0.4.0",
"passport-local": "^1.0.0",
@ -126,14 +124,12 @@
"serve-static": "^1.13.1",
"set-cookie-parser": "^2.3.5",
"source-map-support": "^0.5.16",
"split-lines": "^2.0.0",
"split2": "^3.1.1",
"stack-chain": "^2.0.0",
"stoppable": "^1.0.5",
"struct-fu": "^1.2.0",
"subleveldown": "^5.0.1",
"tar-stream": "^2.0.1",
"through2": "^4.0.2",
"tmp": "^0.2.1",
"unzipper": "^0.10.5",
"uuid": "^8.3.1",

View File

@ -52,16 +52,6 @@ export function getSuggestedExcludedTags() {
return ['Continuous Replication', 'Disaster Recovery', 'XOSAN', this.config.get('xo-proxy.vmTag')]
}
export function migrateLegacyJob({ id }) {
return this.migrateLegacyBackupJob(id)
}
migrateLegacyJob.permission = 'admin'
migrateLegacyJob.params = {
id: {
type: 'string',
},
}
export function deleteJob({ id }) {
return this.deleteBackupNgJob(id)
}

View File

@ -1,99 +0,0 @@
import archiver from 'archiver'
import { basename } from 'path'
import { createLogger } from '@xen-orchestra/log'
import { format } from 'json-rpc-peer'
import { forEach } from 'lodash'
const log = createLogger('xo:backup')
// ===================================================================
export function list({ remote }) {
return this.listVmBackups(remote)
}
list.permission = 'admin'
list.params = {
remote: { type: 'string' },
}
// -------------------------------------------------------------------
export function scanDisk({ remote, disk }) {
return this.scanDiskBackup(remote, disk)
}
scanDisk.permission = 'admin'
scanDisk.params = {
remote: { type: 'string' },
disk: { type: 'string' },
}
// -------------------------------------------------------------------
export function scanFiles({ remote, disk, partition, path }) {
return this.scanFilesInDiskBackup(remote, disk, partition, path)
}
scanFiles.permission = 'admin'
scanFiles.params = {
remote: { type: 'string' },
disk: { type: 'string' },
partition: { type: 'string', optional: true },
path: { type: 'string' },
}
// -------------------------------------------------------------------
function handleFetchFiles(req, res, { remote, disk, partition, paths, format: archiveFormat }) {
return this.fetchFilesInDiskBackup(remote, disk, partition, paths).then(files => {
res.setHeader('content-disposition', 'attachment')
res.setHeader('content-type', 'application/octet-stream')
const nFiles = paths.length
// Send lone file directly
if (nFiles === 1) {
files[0].pipe(res)
return
}
const archive = archiver(archiveFormat)
archive.on('error', error => {
log.error(error)
res.end(format.error(0, error))
})
forEach(files, file => {
archive.append(file, { name: basename(file.path) })
})
archive.finalize()
archive.pipe(res)
})
}
export async function fetchFiles({ format = 'zip', ...params }) {
const fileName = params.paths.length > 1 ? `restore_${new Date().toJSON()}.${format}` : basename(params.paths[0])
return this.registerHttpRequest(
handleFetchFiles,
{ ...params, format },
{
suffix: '/' + encodeURIComponent(fileName),
}
).then(url => ({ $getFrom: url }))
}
fetchFiles.permission = 'admin'
fetchFiles.params = {
remote: { type: 'string' },
disk: { type: 'string' },
format: { type: 'string', optional: true },
partition: { type: 'string', optional: true },
paths: {
type: 'array',
items: { type: 'string' },
minLength: 1,
},
}

View File

@ -31,17 +31,6 @@ test.description = 'Performs a read/write matching test on a remote point'
test.params = {
id: { type: 'string' },
}
export async function list({ id }) {
return this.listRemoteBackups(id)
}
list.permission = 'admin'
list.description = 'Lists the files found in a remote point'
list.params = {
id: { type: 'string' },
}
export function create(props) {
return this.createRemote(props)
}

View File

@ -1,27 +0,0 @@
import execa from 'execa'
import splitLines from 'split-lines'
import { createParser } from 'parse-pairs'
// ===================================================================
const parse = createParser({
keyTransform: key => key.slice(5).toLowerCase(),
})
const makeFunction = command => async (fields, ...args) => {
const { stdout } = await execa(command, [
'--noheading',
'--nosuffix',
'--nameprefixes',
'--unbuffered',
'--units',
'b',
'-o',
String(fields),
...args,
])
return splitLines(stdout).map(Array.isArray(fields) ? parse : line => parse(line)[fields])
}
export const lvs = makeFunction('lvs')
export const pvs = makeFunction('pvs')

View File

@ -1,12 +0,0 @@
import through2 from 'through2'
const createSizeStream = () => {
const wrapper = through2((chunk, enc, cb) => {
wrapper.size += chunk.length
cb(null, chunk)
})
wrapper.size = 0
return wrapper
}
export { createSizeStream as default }

View File

@ -22,7 +22,6 @@ import { filter, find, flatMap, flatten, groupBy, identity, includes, isEmpty, n
import { Ref } from 'xen-api'
import { satisfies as versionSatisfies } from 'semver'
import createSizeStream from '../size-stream.js'
import ensureArray from '../_ensureArray.js'
import fatfsBuffer, { init as fatfsBufferInit } from '../fatfs-buffer.js'
import { asyncMapValues } from '../_asyncMapValues.js'
@ -411,19 +410,15 @@ export default class Xapi extends XapiBase {
}
const sr = targetXapi.getObject(targetSrId)
let stream = await this.exportVm(vmId, {
const stream = await this.exportVm(vmId, {
compress,
})
const sizeStream = createSizeStream()
stream = stream.pipe(sizeStream)
const onVmCreation = nameLabel !== undefined ? vm => vm.set_name_label(nameLabel) : null
const vm = await targetXapi._getOrWaitObject(await targetXapi._importVm(stream, sr, onVmCreation))
return {
size: sizeStream.size,
vm,
}
}

View File

@ -16,8 +16,6 @@ import { handleBackupLog } from '../../_handleBackupLog.js'
import { unboxIdsFromPattern } from '../../utils.js'
import { waitAll } from '../../_waitAll.js'
import { translateLegacyJob } from './migration.js'
const log = createLogger('xo:xo-mixins:backups-ng')
const parseVmBackupId = id => {
@ -519,9 +517,4 @@ export default class BackupNg {
return backupsByVmByRemote
}
async migrateLegacyBackupJob(jobId) {
const [job, schedules] = await Promise.all([this._app.getJob(jobId, 'call'), this._app.getAllSchedules()])
await this._app.updateJob(translateLegacyJob(job, schedules), false)
}
}

View File

@ -1,129 +0,0 @@
import assert from 'assert'
const createOr = children => (children.length === 1 ? children[0] : { __or: children })
const methods = {
'vm.deltaCopy': (job, { _reportWhen: reportWhen, retention = 1, sr, vms }, schedule) => ({
mode: 'delta',
settings: {
'': reportWhen === undefined ? undefined : { reportWhen },
[schedule.id]: {
copyRetention: retention,
vmTimeout: job.timeout,
},
},
srs: { id: sr },
userId: job.userId,
vms,
}),
'vm.rollingDeltaBackup': (job, { _reportWhen: reportWhen, depth = 1, retention = depth, remote, vms }, schedule) => ({
mode: 'delta',
remotes: { id: remote },
settings: {
'': reportWhen === undefined ? undefined : { reportWhen },
[schedule.id]: {
exportRetention: retention,
vmTimeout: job.timeout,
},
},
vms,
}),
'vm.rollingDrCopy': (
job,
{ _reportWhen: reportWhen, deleteOldBackupsFirst, depth = 1, retention = depth, sr, vms },
schedule
) => ({
mode: 'full',
settings: {
'': reportWhen === undefined ? undefined : { reportWhen },
[schedule.id]: {
deleteFirst: deleteOldBackupsFirst,
copyRetention: retention,
vmTimeout: job.timeout,
},
},
srs: { id: sr },
vms,
}),
'vm.rollingBackup': (
job,
{ _reportWhen: reportWhen, compress, depth = 1, retention = depth, remoteId, vms },
schedule
) => ({
compression: compress ? 'native' : undefined,
mode: 'full',
remotes: { id: remoteId },
settings: {
'': reportWhen === undefined ? undefined : { reportWhen },
[schedule.id]: {
exportRetention: retention,
vmTimeout: job.timeout,
},
},
vms,
}),
'vm.rollingSnapshot': (job, { _reportWhen: reportWhen, depth = 1, retention = depth, vms }, schedule) => ({
mode: 'full',
settings: {
'': reportWhen === undefined ? undefined : { reportWhen },
[schedule.id]: {
snapshotRetention: retention,
vmTimeout: job.timeout,
},
},
vms,
}),
}
const parseParamsVector = vector => {
assert.strictEqual(vector.type, 'crossProduct')
const { items } = vector
assert.strictEqual(items.length, 2)
let vms, params
if (items[1].type === 'map') {
;[params, vms] = items
vms = vms.collection
assert.strictEqual(vms.type, 'fetchObjects')
vms = vms.pattern
} else {
;[vms, params] = items
assert.strictEqual(vms.type, 'set')
vms = vms.values
if (vms.length !== 0) {
assert.deepStrictEqual(Object.keys(vms[0]), ['id'])
vms = { id: createOr(vms.map(_ => _.id)) }
}
}
assert.strictEqual(params.type, 'set')
params = params.values
assert.strictEqual(params.length, 1)
params = params[0]
return { ...params, vms }
}
export const translateLegacyJob = (job, schedules) => {
const { id } = job
let method, schedule
if (
id.includes(':') ||
job.type !== 'call' ||
(method = methods[job.method]) === undefined ||
(schedule = schedules.find(_ => _.jobId === id)) === undefined ||
schedule.id.includes(':')
) {
throw new Error(`cannot convert job ${job.id}`)
}
const params = parseParamsVector(job.paramsVector)
return {
id,
name: params.tag || job.name,
type: 'backup',
userId: job.userId,
...method(job, params, schedule),
}
}

File diff suppressed because it is too large Load Diff

115
yarn.lock
View File

@ -2413,35 +2413,6 @@ aproba@^1.0.3, aproba@^1.1.1:
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
archiver-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2"
integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==
dependencies:
glob "^7.1.4"
graceful-fs "^4.2.0"
lazystream "^1.0.0"
lodash.defaults "^4.2.0"
lodash.difference "^4.5.0"
lodash.flatten "^4.4.0"
lodash.isplainobject "^4.0.6"
lodash.union "^4.6.0"
normalize-path "^3.0.0"
readable-stream "^2.0.0"
archiver@^5.0.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.0.tgz#dd3e097624481741df626267564f7dd8640a45ba"
integrity sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==
dependencies:
archiver-utils "^2.1.0"
async "^3.2.0"
buffer-crc32 "^0.2.1"
readable-stream "^3.6.0"
readdir-glob "^1.0.0"
tar-stream "^2.2.0"
zip-stream "^4.1.0"
archy@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
@ -2753,11 +2724,6 @@ async@^2.6.2, async@~2.6.3:
dependencies:
lodash "^4.17.14"
async@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@ -3466,7 +3432,7 @@ buffer-alloc@^1.2.0:
buffer-alloc-unsafe "^1.1.0"
buffer-fill "^1.0.0"
buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
@ -4293,16 +4259,6 @@ component-emitter@^1.2.1:
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
compress-commons@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-4.1.0.tgz#25ec7a4528852ccd1d441a7d4353cd0ece11371b"
integrity sha512-ofaaLqfraD1YRTkrRKPCrGJ1pFeDG/MVCkVVV2FNGeWquSlqw5wOrwOfPQ1xF2u+blpeWASie5EubHz+vsNIgA==
dependencies:
buffer-crc32 "^0.2.13"
crc32-stream "^4.0.1"
normalize-path "^3.0.0"
readable-stream "^3.6.0"
compressible@^2.0.0, compressible@~2.0.16:
version "2.0.18"
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
@ -4569,22 +4525,6 @@ cosmiconfig@^7.0.0:
path-type "^4.0.0"
yaml "^1.10.0"
crc-32@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208"
integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==
dependencies:
exit-on-epipe "~1.0.1"
printj "~1.1.0"
crc32-stream@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-4.0.2.tgz#c922ad22b38395abe9d3870f02fa8134ed709007"
integrity sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==
dependencies:
crc-32 "^1.2.0"
readable-stream "^3.4.0"
create-ecdh@^4.0.0:
version "4.0.4"
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
@ -6603,11 +6543,6 @@ exenv@^1.2.0:
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=
exit-on-epipe@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==
exit@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
@ -10627,16 +10562,6 @@ lodash.debounce@^4.0.8:
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
lodash.defaults@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
lodash.difference@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
integrity sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=
lodash.escape@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698"
@ -10694,11 +10619,6 @@ lodash.isequal@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash.isplainobject@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
lodash.kebabcase@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"
@ -10776,11 +10696,6 @@ lodash.truncate@^4.4.2:
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
lodash.union@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@ -13294,11 +13209,6 @@ pretty-time@^1.1.0:
resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e"
integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==
printj@~1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==
prismjs@^1.13.0:
version "1.23.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.23.0.tgz#d3b3967f7d72440690497652a9d40ff046067f33"
@ -14329,13 +14239,6 @@ readable-stream@~1.0.17:
isarray "0.0.1"
string_decoder "~0.10.x"
readdir-glob@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.1.tgz#f0e10bb7bf7bfa7e0add8baffdc54c3f7dbee6c4"
integrity sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==
dependencies:
minimatch "^3.0.4"
readdirp@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
@ -15516,11 +15419,6 @@ speedometer@~1.0.0:
resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-1.0.0.tgz#cd671cb06752c22bca3370e2f334440be4fc62e2"
integrity sha1-zWccsGdSwivKM3Di8zREC+T8YuI=
split-lines@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/split-lines/-/split-lines-2.1.0.tgz#3bc9dbf75637c8bae6ed5dcbc7dbd83956b72311"
integrity sha512-8dv+1zKgTpfTkOy8XZLFyWrfxO0NV/bj/3EaQ+hBrBxGv2DwiroljPjU8NlCr+59nLnsVm9WYT7lXKwe4TC6bw==
split-string@^3.0.1, split-string@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
@ -16137,7 +16035,7 @@ tapable@^1.0.0, tapable@^1.1.3:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
tar-stream@^2.0.1, tar-stream@^2.2.0:
tar-stream@^2.0.1:
version "2.2.0"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
@ -18087,12 +17985,3 @@ zepto@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/zepto/-/zepto-1.2.0.tgz#e127bd9e66fd846be5eab48c1394882f7c0e4f98"
integrity sha1-4Se9nmb9hGvl6rSME5SIL3wOT5g=
zip-stream@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79"
integrity sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==
dependencies:
archiver-utils "^2.1.0"
compress-commons "^4.1.0"
readable-stream "^3.6.0"