Skip to content

Commit

Permalink
[plugins] Ensures X-Pack is available during plugin install (#19426)
Browse files Browse the repository at this point in the history
For the default distribution, we were not including X-Pack during plugin installation. This broke plugin installation which relied on X-Pack interfaces.

Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
  • Loading branch information
tylersmalley authored and Tyler Smalley committed May 25, 2018
1 parent 194aba1 commit b57aed8
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 118 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
"elasticsearch-browser": "^14.2.1",
"encode-uri-query": "1.0.0",
"even-better": "7.0.2",
"execa": "^0.10.0",
"expiry-js": "0.1.7",
"extract-text-webpack-plugin": "3.0.1",
"fetch-mock": "^5.13.1",
Expand Down
50 changes: 18 additions & 32 deletions src/cli_plugin/install/kibana.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import _ from 'lodash';
import path from 'path';
import { fromRoot } from '../../utils';
import KbnServer from '../../server/kbn_server';
import { readYamlConfig } from '../../cli/serve/read_yaml_config';
import execa from 'execa';
import { fromRoot, watchStdioForLine } from '../../utils';
import { versionSatisfies, cleanVersion } from '../../utils/version';
import { statSync } from 'fs';

Expand All @@ -19,34 +17,22 @@ export function existingInstall(settings, logger) {

export async function rebuildCache(settings, logger) {
logger.log('Optimizing and caching browser bundles...');
const serverConfig = _.merge(
readYamlConfig(settings.config),
{
env: 'production',
logging: {
silent: settings.silent,
quiet: !settings.silent,
verbose: false
},
optimize: {
useBundleCache: false
},
server: {
autoListen: false
},
plugins: {
initialize: false,
scanDirs: [settings.pluginDir, fromRoot('src/core_plugins')]
},
uiSettings: {
enabled: false
}
}
);

const kbnServer = new KbnServer(serverConfig);
await kbnServer.ready();
await kbnServer.close();

const kibanaArgs = [
fromRoot('./src/cli'),
'--env.name=production',
'--optimize.useBundleCache=false',
'--server.autoListen=false',
'--plugins.initialize=false',
'--uiSettings.enabled=false'
];

const proc = execa(process.execPath, kibanaArgs, {
stdio: ['ignore', 'pipe', 'pipe'],
cwd: fromRoot('.'),
});

await watchStdioForLine(proc, () => {}, /Optimization .+ complete/);
}

export function assertVersion(settings) {
Expand Down
31 changes: 1 addition & 30 deletions src/dev/build/lib/__tests__/exec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { resolve } from 'path';

import sinon from 'sinon';
import stripAnsi from 'strip-ansi';

Expand Down Expand Up @@ -32,31 +30,4 @@ describe('dev/build/lib/exec', () => {
// log output of the process
sinon.assert.calledWithExactly(onLogLine, sinon.match(/info\s+hi/));
});

it('send the proc SIGKILL if it logs a line matching exitAfter regexp', async function () {
// fixture proc will exit after 10 seconds if sigint not received, but the test won't fail
// unless we see the log line `SIGINT not received`, so we let the test take up to 30 seconds
// for potentially huge delays here and there
this.timeout(30000);

await exec(log, process.execPath, [require.resolve('./fixtures/log_on_sigint')], {
exitAfter: /listening for SIGINT/
});

sinon.assert.calledWithExactly(onLogLine, sinon.match(/listening for SIGINT/));
sinon.assert.neverCalledWith(onLogLine, sinon.match(/SIGINT not received/));
});

it('logs using level: option', async () => {
const parentDir = resolve(process.cwd(), '..');

await exec(log, process.execPath, ['-e', 'console.log(process.cwd())'], {
level: 'info',
cwd: parentDir,
});

// log output of the process, checking for \n to ensure cwd() doesn't log
// the subdir that this process is executing in
sinon.assert.calledWithExactly(onLogLine, sinon.match(parentDir + '\n'));
});
});
});
58 changes: 2 additions & 56 deletions src/dev/build/lib/exec.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,7 @@
import execa from 'execa';
import chalk from 'chalk';
import { Transform } from 'stream';

import {
createPromiseFromStreams,
createSplitStream,
createMapStream,
} from '../../../utils';

// creates a stream that skips empty lines unless they are followed by
// another line, preventing the empty lines produced by splitStream
function skipLastEmptyLineStream() {
let skippedEmptyLine = false;
return new Transform({
objectMode: true,
transform(line, enc, cb) {
if (skippedEmptyLine) {
this.push('');
skippedEmptyLine = false;
}

if (line === '') {
skippedEmptyLine = true;
return cb();
} else {
return cb(null, line);
}
}
});
}
import { watchStdioForLine } from '../../../utils';

export async function exec(log, cmd, args, options = {}) {
const {
Expand All @@ -44,32 +17,5 @@ export async function exec(log, cmd, args, options = {}) {
cwd,
});

function onLogLine(line) {
log[level](line);

if (exitAfter && exitAfter.test(line)) {
proc.kill('SIGINT');
}
}

await Promise.all([
proc.catch(error => {
// ignore the error thrown by execa if it's because we killed with SIGINT
if (error.signal !== 'SIGINT') {
throw error;
}
}),
createPromiseFromStreams([
proc.stdout,
createSplitStream('\n'),
skipLastEmptyLineStream(),
createMapStream(onLogLine),
]),
createPromiseFromStreams([
proc.stderr,
createSplitStream('\n'),
skipLastEmptyLineStream(),
createMapStream(onLogLine),
]),
]);
await watchStdioForLine(proc, line => log[level](line), exitAfter);
}
36 changes: 36 additions & 0 deletions src/utils/__tests__/watch_stdio_for_line.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import execa from 'execa';
import stripAnsi from 'strip-ansi';
import sinon from 'sinon';

import { watchStdioForLine } from '../watch_stdio_for_line';

describe('src/utils/watch_stdio_for_line', function () {
const sandbox = sinon.sandbox.create();
afterEach(() => sandbox.reset());

const onLogLine = sandbox.stub();
const logFn = line => onLogLine(stripAnsi(line));

it('calls logFn with log lines', async () => {
const proc = execa(process.execPath, ['-e', 'console.log("hi")']);

await watchStdioForLine(proc, logFn);

// log output of the process
sinon.assert.calledWithExactly(onLogLine, sinon.match(/hi/));
});

it('send the proc SIGKILL if it logs a line matching exitAfter regexp', async function () {
// fixture proc will exit after 10 seconds if sigint not received, but the test won't fail
// unless we see the log line `SIGINT not received`, so we let the test take up to 30 seconds
// for potentially huge delays here and there
this.timeout(30000);

const proc = execa(process.execPath, [require.resolve('./fixtures/log_on_sigint')]);

await watchStdioForLine(proc, logFn, /listening for SIGINT/);

sinon.assert.calledWithExactly(onLogLine, sinon.match(/listening for SIGINT/));
sinon.assert.neverCalledWith(onLogLine, sinon.match(/SIGINT not received/));
});
});
1 change: 1 addition & 0 deletions src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export { unset } from './unset';
export { encodeQueryComponent } from './encode_query_component';
export { modifyUrl } from './modify_url';
export { getFlattenedObject } from './get_flattened_object';
export { watchStdioForLine } from './watch_stdio_for_line';

export {
getKbnTypeNames,
Expand Down
60 changes: 60 additions & 0 deletions src/utils/watch_stdio_for_line.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Transform } from 'stream';

import {
createPromiseFromStreams,
createSplitStream,
createMapStream,
} from './streams';

// creates a stream that skips empty lines unless they are followed by
// another line, preventing the empty lines produced by splitStream
function skipLastEmptyLineStream() {
let skippedEmptyLine = false;
return new Transform({
objectMode: true,
transform(line, enc, cb) {
if (skippedEmptyLine) {
this.push('');
skippedEmptyLine = false;
}

if (line === '') {
skippedEmptyLine = true;
return cb();
} else {
return cb(null, line);
}
}
});
}

export async function watchStdioForLine(proc, logFn, exitAfter) {
function onLogLine(line) {
logFn(line);

if (exitAfter && exitAfter.test(line)) {
proc.kill('SIGINT');
}
}

await Promise.all([
proc.catch(error => {
// ignore the error thrown by execa if it's because we killed with SIGINT
if (error.signal !== 'SIGINT') {
throw error;
}
}),
createPromiseFromStreams([
proc.stdout,
createSplitStream('\n'),
skipLastEmptyLineStream(),
createMapStream(onLogLine),
]),
createPromiseFromStreams([
proc.stderr,
createSplitStream('\n'),
skipLastEmptyLineStream(),
createMapStream(onLogLine),
]),
]);
}

0 comments on commit b57aed8

Please sign in to comment.