[plugins] Ensures X-Pack is available during plugin install (#19426)

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>
This commit is contained in:
Tyler Smalley 2018-05-25 11:57:40 -07:00 committed by Tyler Smalley
parent 194aba149f
commit b57aed821a
8 changed files with 118 additions and 117 deletions

View file

@ -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",

View file

@ -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';
@ -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) {

View file

@ -1,5 +1,3 @@
import { resolve } from 'path';
import sinon from 'sinon';
import stripAnsi from 'strip-ansi';
@ -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'));
});
});
});

View file

@ -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 {
@ -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);
}

View file

@ -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/));
});
});

View file

@ -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,

View file

@ -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),
]),
]);
}