[plugin cli] Retry folder rename on windows eperm (#9279)

Backports PR #9260

**Commit 1:**
[plugin cli] Retry folder rename on windows eperm

* Original sha: 398662fc84
* Authored by Jonathan Budzenski <jon@jbudz.me> on 2016-11-29T20:05:19Z
This commit is contained in:
jasper 2016-11-30 13:23:55 -05:00 committed by Court Ewing
parent 59b31e5b3d
commit 0fd25ab9ea
3 changed files with 95 additions and 2 deletions

View file

@ -0,0 +1,72 @@
import expect from 'expect.js';
import sinon from 'sinon';
import fs from 'fs';
import { renamePlugin } from '../rename';
describe('plugin folder rename', function () {
let renameStub;
beforeEach(function () {
renameStub = sinon.stub();
});
afterEach(function () {
fs.rename.restore();
});
it('should rethrow any exceptions', function () {
renameStub = sinon.stub(fs, 'rename', function (from, to, cb) {
cb({
code: 'error'
});
});
return renamePlugin('/foo/bar', '/bar/foo')
.catch(function (err) {
expect(err.code).to.be('error');
expect(renameStub.callCount).to.be(1);
});
});
it('should resolve if there are no errors', function () {
renameStub = sinon.stub(fs, 'rename', function (from, to, cb) {
cb();
});
return renamePlugin('/foo/bar', '/bar/foo')
.then(function (err) {
expect(renameStub.callCount).to.be(1);
})
.catch(function () {
throw new Error('We shouln\'t have any errors');
});
});
describe('Windows', function () {
let platform;
beforeEach(function () {
platform = Object.getOwnPropertyDescriptor(process, 'platform');
Object.defineProperty(process, 'platform', {
value: 'win32'
});
});
afterEach(function () {
Object.defineProperty(process, 'platform', platform);
});
it('should retry on Windows EPERM errors for up to 3 seconds', function () {
this.timeout(5000);
renameStub = sinon.stub(fs, 'rename', function (from, to, cb) {
cb({
code: 'EPERM'
});
});
return renamePlugin('/foo/bar', '/bar/foo')
.catch(function (err) {
expect(err.code).to.be('EPERM');
expect(renameStub.callCount).to.be.greaterThan(1);
});
});
});
});

View file

@ -2,8 +2,8 @@ import { download } from './download';
import Promise from 'bluebird';
import { cleanPrevious, cleanArtifacts } from './cleanup';
import { extract, getPackData } from './pack';
import { renamePlugin } from './rename';
import { sync as rimrafSync } from 'rimraf';
import { renameSync } from 'fs';
import { existingInstall, rebuildCache, assertVersion } from './kibana';
import mkdirp from 'mkdirp';
@ -27,7 +27,7 @@ export default async function install(settings, logger) {
assertVersion(settings);
renameSync(settings.workingPath, settings.plugins[0].path);
await renamePlugin(settings.workingPath, settings.plugins[0].path);
await rebuildCache(settings, logger);

View file

@ -0,0 +1,21 @@
import { rename } from 'fs';
import { delay } from 'lodash';
export function renamePlugin(workingPath, finalPath) {
return new Promise(function (resolve, reject) {
const start = Date.now();
const retryTime = 3000;
const retryDelay = 100;
rename(workingPath, finalPath, function retry(err) {
if (err) {
// In certain cases on Windows, such as running AV, plugin folders can be locked shortly after extracting
// Retry for up to retryTime seconds
const windowsEPERM = process.platform === 'win32' && err.code === 'EPERM';
const retryAvailable = Date.now() - start < retryTime;
if (windowsEPERM && retryAvailable) return delay(rename, retryDelay, workingPath, finalPath, retry);
reject(err);
}
resolve();
});
});
}