Skip to content

Commit

Permalink
[plugin cli] Retry folder rename on windows eperm (#9278)
Browse files Browse the repository at this point in the history
Backports PR #9260

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

* Original sha: 398662f
* Authored by Jonathan Budzenski <[email protected]> on 2016-11-29T20:05:19Z
  • Loading branch information
elastic-jasper authored and epixa committed Nov 30, 2016
1 parent e1456a8 commit 17df55c
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 2 deletions.
72 changes: 72 additions & 0 deletions src/cli_plugin/install/__tests__/rename.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
});
});
4 changes: 2 additions & 2 deletions src/cli_plugin/install/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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);

Expand Down
21 changes: 21 additions & 0 deletions src/cli_plugin/install/rename.js
Original file line number Diff line number Diff line change
@@ -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();
});
});
}

0 comments on commit 17df55c

Please sign in to comment.