Skip to content

Commit

Permalink
Merge pull request #5843 from spalger/implement/randomBasePathInDev
Browse files Browse the repository at this point in the history
[server/dev] inject a random basepath
  • Loading branch information
spalger committed Jan 19, 2016
2 parents d2b4297 + 60d3c40 commit 6150fe6
Show file tree
Hide file tree
Showing 10 changed files with 193 additions and 80 deletions.
98 changes: 98 additions & 0 deletions src/cli/cluster/base_path_proxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { Server } from 'hapi';
import { notFound } from 'boom';
import { merge, sample } from 'lodash';
import { format as formatUrl } from 'url';
import { fromNode } from 'bluebird';
import { Agent as HttpsAgent } from 'https';
import { readFileSync } from 'fs';

import Config from '../../server/config/config';
import setupConnection from '../../server/http/setup_connection';
import setupLogging from '../../server/logging';

const alphabet = 'abcdefghijklmnopqrztuvwxyz'.split('');

export default class BasePathProxy {
constructor(clusterManager, userSettings) {
this.clusterManager = clusterManager;
this.server = new Server();

const config = Config.withDefaultSchema(userSettings);

this.targetPort = config.get('dev.basePathProxyTarget');
this.basePath = config.get('server.basePath');

const { cert } = config.get('server.ssl');
if (cert) {
this.proxyAgent = new HttpsAgent({
ca: readFileSync(cert)
});
}

if (!this.basePath) {
this.basePath = `/${sample(alphabet, 3).join('')}`;
config.set('server.basePath', this.basePath);
}

setupLogging(null, this.server, config);
setupConnection(null, this.server, config);
this.setupRoutes();
}

setupRoutes() {
const { server, basePath, targetPort } = this;

server.route({
method: 'GET',
path: '/',
handler(req, reply) {
return reply.redirect(basePath);
}
});

server.route({
method: '*',
path: `${basePath}/{kbnPath*}`,
handler: {
proxy: {
passThrough: true,
xforward: true,
agent: this.proxyAgent,
mapUri(req, callback) {
callback(null, formatUrl({
protocol: server.info.protocol,
hostname: server.info.host,
port: targetPort,
pathname: req.params.kbnPath,
query: req.query,
}));
}
}
}
});

server.route({
method: '*',
path: `/{oldBasePath}/{kbnPath*}`,
handler(req, reply) {
const {oldBasePath, kbnPath = ''} = req.params;

const isGet = req.method === 'get';
const isBasePath = oldBasePath.length === 3;
const isApp = kbnPath.slice(0, 4) === 'app/';

if (isGet && isBasePath && isApp) {
return reply.redirect(`${basePath}/${kbnPath}`);
}

return reply(notFound());
}
});
}

async listen() {
await fromNode(cb => this.server.start(cb));
this.server.log(['listening', 'info'], `basePath Proxy running at ${this.server.info.uri}${this.basePath}`);
}

}
43 changes: 28 additions & 15 deletions src/cli/cluster/cluster_manager.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,42 @@
let cluster = require('cluster');
let { join } = require('path');
let { debounce, compact, invoke, bindAll, once } = require('lodash');
const cluster = require('cluster');
const { join } = require('path');
const { format: formatUrl } = require('url');
const Hapi = require('hapi');
const { debounce, compact, get, invoke, bindAll, once, sample } = require('lodash');

let Log = require('../Log');
let Worker = require('./worker');
const Log = require('../Log');
const Worker = require('./worker');
const BasePathProxy = require('./base_path_proxy');

process.env.kbnWorkerType = 'managr';

module.exports = class ClusterManager {
constructor(opts) {
constructor(opts, settings) {
this.log = new Log(opts.quiet, opts.silent);
this.addedCount = 0;

this.basePathProxy = new BasePathProxy(this, settings);

this.workers = [
this.optimizer = new Worker({
type: 'optmzr',
title: 'optimizer',
log: this.log,
argv: compact([
'--plugins.initialize=false',
'--server.autoListen=false'
'--server.autoListen=false',
`--server.basePath=${this.basePathProxy.basePath}`
]),
watch: false
}),

this.server = new Worker({
type: 'server',
log: this.log
log: this.log,
argv: compact([
`--server.port=${this.basePathProxy.targetPort}`,
`--server.basePath=${this.basePathProxy.basePath}`
])
})
];

Expand All @@ -48,12 +60,13 @@ module.exports = class ClusterManager {
startCluster() {
this.setupManualRestart();
invoke(this.workers, 'start');
this.basePathProxy.listen();
}

setupWatching() {
var chokidar = require('chokidar');
let utils = require('requirefrom')('src/utils');
let fromRoot = utils('fromRoot');
const chokidar = require('chokidar');
const utils = require('requirefrom')('src/utils');
const fromRoot = utils('fromRoot');

this.watcher = chokidar.watch([
'src/plugins',
Expand Down Expand Up @@ -81,12 +94,12 @@ module.exports = class ClusterManager {
}

setupManualRestart() {
let readline = require('readline');
let rl = readline.createInterface(process.stdin, process.stdout);
const readline = require('readline');
const rl = readline.createInterface(process.stdin, process.stdout);

let nls = 0;
let clear = () => nls = 0;
let clearSoon = debounce(clear, 2000);
const clear = () => nls = 0;
const clearSoon = debounce(clear, 2000);

rl.setPrompt('');
rl.prompt();
Expand Down
114 changes: 60 additions & 54 deletions src/cli/serve/serve.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
let _ = require('lodash');
let { isWorker } = require('cluster');
let { resolve } = require('path');
const _ = require('lodash');
const { isWorker } = require('cluster');
const { resolve } = require('path');

let cwd = process.cwd();
let src = require('requirefrom')('src');
let fromRoot = src('utils/fromRoot');
const cwd = process.cwd();
const src = require('requirefrom')('src');
const fromRoot = src('utils/fromRoot');

let canCluster;
try {
Expand All @@ -14,19 +14,61 @@ try {
canCluster = false;
}

let pathCollector = function () {
let paths = [];
const pathCollector = function () {
const paths = [];
return function (path) {
paths.push(resolve(process.cwd(), path));
return paths;
};
};

let pluginDirCollector = pathCollector();
let pluginPathCollector = pathCollector();
const pluginDirCollector = pathCollector();
const pluginPathCollector = pathCollector();

function initServerSettings(opts, extraCliOptions) {
const readYamlConfig = require('./read_yaml_config');
const settings = readYamlConfig(opts.config);
const set = _.partial(_.set, settings);
const get = _.partial(_.get, settings);
const has = _.partial(_.has, settings);
const merge = _.partial(_.merge, settings);

if (opts.dev) {
try { merge(readYamlConfig(fromRoot('config/kibana.dev.yml'))); }
catch (e) { null; }
}

if (opts.dev) {
set('env', 'development');
set('optimize.lazy', true);
if (opts.ssl && !has('server.ssl.cert') && !has('server.ssl.key')) {
set('server.host', 'localhost');
set('server.ssl.cert', fromRoot('test/dev_certs/server.crt'));
set('server.ssl.key', fromRoot('test/dev_certs/server.key'));
}
}

if (opts.elasticsearch) set('elasticsearch.url', opts.elasticsearch);
if (opts.port) set('server.port', opts.port);
if (opts.host) set('server.host', opts.host);
if (opts.quiet) set('logging.quiet', true);
if (opts.silent) set('logging.silent', true);
if (opts.verbose) set('logging.verbose', true);
if (opts.logFile) set('logging.dest', opts.logFile);

set('plugins.scanDirs', _.compact([].concat(
get('plugins.scanDirs'),
opts.pluginDir
)));

set('plugins.paths', [].concat(opts.pluginPath || []));
merge(extraCliOptions);

return settings;
}

module.exports = function (program) {
let command = program.command('serve');
const command = program.command('serve');

command
.description('Run the kibana server')
Expand Down Expand Up @@ -70,59 +112,23 @@ module.exports = function (program) {

command
.action(async function (opts) {
const settings = initServerSettings(opts, this.getUnknownOptions());

if (canCluster && opts.dev && !isWorker) {
// stop processing the action and handoff to cluster manager
let ClusterManager = require('../cluster/cluster_manager');
new ClusterManager(opts);
const ClusterManager = require('../cluster/cluster_manager');
new ClusterManager(opts, settings);
return;
}

let readYamlConfig = require('./read_yaml_config');
let KbnServer = src('server/KbnServer');

let settings = readYamlConfig(opts.config);

if (opts.dev) {
try { _.merge(settings, readYamlConfig(fromRoot('config/kibana.dev.yml'))); }
catch (e) { null; }
}

let set = _.partial(_.set, settings);
let get = _.partial(_.get, settings);
const has = _.partial(_.has, settings);

if (opts.dev) {
set('env', 'development');
set('optimize.lazy', true);
if (opts.ssl && !has('server.ssl.cert') && !has('server.ssl.key')) {
set('server.ssl.cert', fromRoot('test/dev_certs/server.crt'));
set('server.ssl.key', fromRoot('test/dev_certs/server.key'));
}
}

if (opts.elasticsearch) set('elasticsearch.url', opts.elasticsearch);
if (opts.port) set('server.port', opts.port);
if (opts.host) set('server.host', opts.host);
if (opts.quiet) set('logging.quiet', true);
if (opts.silent) set('logging.silent', true);
if (opts.verbose) set('logging.verbose', true);
if (opts.logFile) set('logging.dest', opts.logFile);

set('plugins.scanDirs', _.compact([].concat(
get('plugins.scanDirs'),
opts.pluginDir
)));

set('plugins.paths', [].concat(opts.pluginPath || []));

let kbnServer = {};

const KbnServer = src('server/KbnServer');
try {
kbnServer = new KbnServer(_.merge(settings, this.getUnknownOptions()));
kbnServer = new KbnServer(settings);
await kbnServer.ready();
}
catch (err) {
let { server } = kbnServer;
const { server } = kbnServer;

if (server) server.log(['fatal'], err);
console.error('FATAL', err);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ define(function (require) {
}

if (!field.indexed) {
warnings.push('This field is not indexed and can not be visualized.');
warnings.push('This field is not indexed and might not be usable in visualizations.');
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,11 @@ <h5 ng-show="!field.details.error">Quick Count <kbn-info info="Top 5 values base
</div>
</div>

<a ng-show="field.indexed || field.scripted"
<a
ng-href="{{vizLocation(field)}}"
class="sidebar-item-button primary">
Visualize
<span class="discover-field-vis-warning" ng-show="warnings.length" tooltip="{{warnings.join(' ')}}">
( {{::warnings.length}} <ng-pluralize count="warnings.length" when="{'1':'warning', 'other':'warnings'}"></ng-pluralize> <i aria-hidden="true" class="fa fa-warning"></i> )
</span>
</a>

<div ng-show="!field.indexed && !field.scripted"
disabled="disabled"
tooltip="This field is not indexed thus unavailable for visualization and search"
class="sidebar-item-button primary">Not Indexed</div>
1 change: 0 additions & 1 deletion src/plugins/kibana/public/visualize/editor/agg_params.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ define(function (require) {

if (fieldTypes) {
fields = $filter('fieldType')(fields, fieldTypes);
fields = $filter('filter')(fields, { bucketable: true });
fields = $filter('orderBy')(fields, ['type', 'name']);
}

Expand Down
4 changes: 4 additions & 0 deletions src/server/config/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ module.exports = () => Joi.object({
prod: Joi.boolean().default(Joi.ref('$prod'))
}).default(),

dev: Joi.object({
basePathProxyTarget: Joi.number().default(5603),
}).default(),

pid: Joi.object({
file: Joi.string(),
exclusive: Joi.boolean().default(false)
Expand Down
1 change: 1 addition & 0 deletions src/server/logging/log_format_string.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ let typeColors = {
debug: 'brightBlack',
server: 'brightBlack',
optmzr: 'white',
managr: 'green',
optimize: 'magenta',
listening: 'magenta'
};
Expand Down
1 change: 0 additions & 1 deletion src/ui/public/index_patterns/__tests__/_index_pattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ describe('index pattern', function () {

describe('fields', function () {
it('should have expected properties on fields', function () {
expect(indexPattern.fields[0]).to.have.property('bucketable');
expect(indexPattern.fields[0]).to.have.property('displayName');
expect(indexPattern.fields[0]).to.have.property('filterable');
expect(indexPattern.fields[0]).to.have.property('format');
Expand Down
Loading

0 comments on commit 6150fe6

Please sign in to comment.