Merge branch 'master' of github.com:elastic/kibana into chore/packageJsonUpkeep

This commit is contained in:
spalger 2015-08-19 11:13:40 -07:00
commit 4fdb7c7853
78 changed files with 820 additions and 768 deletions

1
.gitignore vendored
View file

@ -5,6 +5,7 @@ node_modules
trash
bundles
target
/build
.jruby
.idea
*.iml

View file

@ -26,16 +26,7 @@ module.exports = function (grunt) {
}
}()),
nodeVersion: '0.10.35',
platforms: ['darwin-x64', 'linux-x64', 'linux-x86', 'windows'],
services: [
['launchd', '10.9'],
['upstart', '1.5'],
['systemd', 'default'],
['sysv', 'lsb-3.1']
],
devPlugins: 'devMode',
nodeVersion: '2.5.0',
meta: {
banner: '/*! <%= package.name %> - v<%= package.version %> - ' +
@ -44,16 +35,40 @@ module.exports = function (grunt) {
' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= package.author.company %>;' +
' Licensed <%= package.license %> */\n'
},
lintThese: [
'Gruntfile.js',
'<%= root %>/tasks/**/*.js',
'<%= src %>/**/*.js',
'!<%= src %>/fixtures/**/*.js'
]
],
deepModules: {
'caniuse-db': '1.0.30000265',
'chalk': '1.1.0',
'glob': '4.5.3',
'har-validator': '1.8.0',
'json5': '0.4.0',
'loader-utils': '0.2.11',
'micromatch': '2.2.0',
'postcss-normalize-url': '2.1.1',
'postcss-reduce-idents': '1.0.2',
'postcss-unique-selectors': '1.0.0',
'postcss-minify-selectors': '1.4.6',
'postcss-single-charset': '0.3.0',
'regenerator': '0.8.36'
}
};
grunt.config.merge(config);
config.userScriptsDir = __dirname + '/build/userScripts';
// ensure that these run first, other configs need them
config.services = require('./tasks/config/services')(grunt);
config.platforms = require('./tasks/config/platforms')(grunt);
grunt.config.merge(config);
// load plugins
require('load-grunt-config')(grunt, {
configPath: __dirname + '/tasks/config',
@ -66,4 +81,5 @@ module.exports = function (grunt) {
// load task definitions
grunt.task.loadTasks('tasks');
grunt.task.loadTasks('tasks/build');
};

View file

@ -81,7 +81,7 @@ If you are using a self-signed certificate for Elasticsearch, set the `ca` prope
[source,text]
----
# If you need to provide a CA certificate for your Elasticsarech instance, put
# If you need to provide a CA certificate for your Elasticsearch instance, put
# the path of the pem file here.
ca: /path/to/your/ca/cacert.pem
----

View file

@ -54,12 +54,12 @@
"angular-nvd3": "panda01/angular-nvd3#kibana",
"angular-route": "1.2.28",
"ansicolors": "^0.3.2",
"auto-preload-rjscommon-deps-loader": "^1.0.4",
"autoprefixer": "^5.2.0",
"autoprefixer-loader": "^2.0.0",
"babel": "^5.8.21",
"babel-core": "^5.8.22",
"babel-loader": "^5.3.2",
"babel-runtime": "^5.8.20",
"bluebird": "^2.9.27",
"boom": "^2.8.0",
"bootstrap": "^3.3.5",
@ -99,9 +99,10 @@
"numeral": "^1.5.3",
"nvd3": "panda01/nvd3#kibana",
"raw-loader": "^0.5.1",
"request": "^2.40.0",
"request": "^2.60.0",
"requirefrom": "^0.2.0",
"rimraf": "^2.4.1",
"rjs-repack-loader": "^1.0.6",
"script-loader": "^0.6.1",
"semver": "^4.3.6",
"style-loader": "^0.12.3",
@ -122,9 +123,9 @@
"faker": "^1.1.0",
"glob": "^4.3.2",
"grunt": "^0.4.5",
"grunt-babel": "^5.0.1",
"grunt-cli": "0.1.13",
"grunt-contrib-clean": "^0.6.0",
"grunt-contrib-compress": "^0.13.0",
"grunt-contrib-copy": "^0.8.0",
"grunt-esvm": "^1.1.3",
"grunt-karma": "^0.12.0",
@ -151,7 +152,8 @@
"portscanner": "^1.0.0",
"simple-git": "^1.3.0",
"sinon": "^1.15.4",
"source-map": "^0.4.4"
"source-map": "^0.4.4",
"wreck": "^6.1.0"
},
"engines": {
"node": ">=2"

View file

@ -64,7 +64,7 @@ module.exports = class ClusterManager {
'installedPlugins'
], {
cwd: fromRoot('.'),
ignored: /[\\\/](node_modules|bower_components|public)[\\\/]/,
ignored: /[\\\/](\..*|node_modules|bower_components|public)[\\\/]/,
});
this.watcher.on('add', this.onWatcherAdd);

12
src/cli/index.build.js Normal file
View file

@ -0,0 +1,12 @@
var _ = require('lodash');
var fromRoot = require('requirefrom')('src/utils')('fromRoot');
var babelOpts = _.defaults({
ignore: [
fromRoot('src'),
/[\\\/](node_modules|bower_components)[\\\/]/
]
}, require('../optimize/babelOptions'));
require('babel/register')(babelOpts);
require('./cli');

View file

@ -1,68 +0,0 @@
var expect = require('expect.js');
var nock = require('nock');
var rimraf = require('rimraf');
var fs = require('fs');
var { join } = require('path');
var sinon = require('sinon');
var pluginLogger = require('../pluginLogger');
var npmInstall = require('../npmInstall');
describe('kibana cli', function () {
describe('plugin installer', function () {
describe('npmInstall', function () {
var testWorkingPath = join(__dirname, '.test.data');
var logger;
var statSyncStub;
beforeEach(function () {
statSyncStub = undefined;
logger = pluginLogger(false);
rimraf.sync(testWorkingPath);
sinon.stub(logger, 'log');
sinon.stub(logger, 'error');
});
afterEach(function () {
logger.log.restore();
logger.error.restore();
rimraf.sync(testWorkingPath);
if (statSyncStub) statSyncStub.restore();
});
it('should throw an error if there is no package.json file in the archive', function () {
fs.mkdirSync(testWorkingPath);
var errorStub = sinon.stub();
return npmInstall(testWorkingPath, logger)
.catch(errorStub)
.then(function (data) {
expect(errorStub.called).to.be(true);
expect(errorStub.lastCall.args[0].message).to.match(/package.json/);
});
});
it('should rethrow any errors other than "ENOENT" from fs.statSync', function () {
fs.mkdirSync(testWorkingPath);
statSyncStub = sinon.stub(fs, 'statSync', function () {
throw new Error('This is unexpected.');
});
var errorStub = sinon.stub();
return npmInstall(testWorkingPath, logger)
.catch(errorStub)
.then(function (data) {
expect(errorStub.called).to.be(true);
expect(errorStub.lastCall.args[0].message).to.match(/This is unexpected./);
});
});
});
});
});

View file

@ -1,35 +0,0 @@
var Promise = require('bluebird');
var fs = require('fs');
var path = require('path');
var exec = require('child_process').exec;
module.exports = function (dest, logger) {
return new Promise(function (resolve, reject) {
//throw an exception if package.json does not exist
try {
var packageFile = path.join(dest, 'package.json');
fs.statSync(packageFile);
} catch (e) {
if (e.code !== 'ENOENT') throw e;
return reject(new Error('Plugin does not contain package.json file'));
}
var cmd = '"' + path.resolve(path.dirname(process.execPath), 'npm').replace(/\\/g, '/') + '" install --production';
var child = exec(cmd, { cwd: dest });
child.on('error', function (err) {
reject(err);
});
child.on('exit', function (code, signal) {
if (code === 0) {
resolve();
} else {
reject(new Error('npm install failed with code ' + code));
}
});
logger.error(child.stderr);
logger.log(child.stdout);
});
};

View file

@ -1,6 +1,5 @@
var pluginDownloader = require('./pluginDownloader');
var pluginCleaner = require('./pluginCleaner');
var npmInstall = require('./npmInstall');
var fs = require('fs');
module.exports = {
@ -26,9 +25,6 @@ function install(settings, logger) {
.then(function () {
return downloader.download();
})
.then(function () {
return npmInstall(settings.workingPath, logger);
})
.then(function (curious) {
fs.renameSync(settings.workingPath, settings.pluginPath);
logger.log('Plugin installation complete');

View file

@ -6,6 +6,14 @@ let cwd = process.cwd();
let src = require('requirefrom')('src');
let fromRoot = src('utils/fromRoot');
let canCluster;
try {
require.resolve('../cluster/ClusterManager');
canCluster = true;
} catch (e) {
canCluster = false;
}
let pathCollector = function () {
let paths = [];
return function (path) {
@ -18,8 +26,9 @@ let pluginDirCollector = pathCollector();
let pluginPathCollector = pathCollector();
module.exports = function (program) {
program
.command('serve')
let command = program.command('serve');
command
.description('Run the kibana server')
.collectUnknownOptions()
.option('-e, --elasticsearch <uri>', 'Elasticsearch instance')
@ -47,11 +56,17 @@ module.exports = function (program) {
pluginPathCollector,
[]
)
.option('--plugins <path>', 'an alias for --plugin-dir', pluginDirCollector)
.option('--dev', 'Run the server with development mode defaults')
.option('--no-watch', 'Prevents automatic restarts of the server in --dev mode')
.option('--plugins <path>', 'an alias for --plugin-dir', pluginDirCollector);
if (canCluster) {
command
.option('--dev', 'Run the server with development mode defaults')
.option('--no-watch', 'Prevents automatic restarts of the server in --dev mode');
}
command
.action(async function (opts) {
if (opts.dev && !isWorker) {
if (canCluster && opts.dev && !isWorker) {
// stop processing the action and handoff to cluster manager
let ClusterManager = require('../cluster/ClusterManager');
new ClusterManager(opts);

View file

@ -11,6 +11,7 @@ var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
let utils = require('requirefrom')('src/utils');
let fromRoot = utils('fromRoot');
let babelOptions = require('./babelOptions');
let babelExclude = [/[\/\\](node_modules|bower_components)[\/\\]/];
class BaseOptimizer {
constructor(opts) {
@ -108,19 +109,19 @@ class BaseOptimizer {
{ test: /\.(html|tmpl)$/, loader: 'raw' },
{ test: /\.png$/, loader: 'url?limit=10000&name=[path][name].[ext]' },
{ test: /\.(woff|woff2|ttf|eot|svg|ico)(\?|$)/, loader: 'file?name=[path][name].[ext]' },
{ test: /[\/\\]src[\/\\](plugins|ui)[\/\\].+\.js$/, loader: `auto-preload-rjscommon-deps${mapQ}` },
{ test: /[\/\\]src[\/\\](plugins|ui)[\/\\].+\.js$/, loader: `rjs-repack${mapQ}` },
{
test: /\.js$/,
exclude: /[\/\\](node_modules|bower_components)[\/\\]/,
exclude: babelExclude.concat(this.env.noParse),
loader: 'babel',
query: babelOptions
},
{
test: /\.jsx$/,
exclude: /[\/\\](node_modules|bower_components)[\/\\]/,
exclude: babelExclude.concat(this.env.noParse),
loader: 'babel',
query: defaults({
nonStandard: true
nonStandard: true,
}, babelOptions)
}
].concat(this.env.loaders),

View file

@ -16,6 +16,9 @@ define(function (require) {
require('plugins/kibana/dashboard/services/saved_dashboards');
require('plugins/kibana/dashboard/styles/main.less');
require('ui/saved_objects/saved_object_registry').register(require('plugins/kibana/dashboard/services/saved_dashboard_register'));
var app = require('ui/modules').get('app/dashboard', [
'elasticsearch',
'ngRoute',
@ -49,6 +52,7 @@ define(function (require) {
app.directive('dashboardApp', function (Notifier, courier, AppState, timefilter, kbnUrl) {
return {
controller: function ($scope, $route, $routeParams, $location, Private, getAppState) {
var queryFilter = Private(require('ui/filter_bar/query_filter'));
var notify = new Notifier({

View file

@ -0,0 +1,5 @@
define(function (require) {
return function savedDashboardFn(savedDashboards) {
return savedDashboards;
};
});

View file

@ -17,6 +17,13 @@ define(function (require) {
this.type = SavedDashboard.type;
this.Class = SavedDashboard;
this.loaderProperties = {
name: 'dashboards',
noun: 'Dashboard',
nouns: 'dashboards'
};
// Returns a single dashboard by ID, should be the name of the dashboard
this.get = function (id) {

View file

@ -8,4 +8,7 @@ define(function (require, module, exports) {
// preload
require('ui/doc_table/components/table_row');
require('ui/saved_objects/saved_object_registry').register(require('plugins/kibana/discover/saved_searches/saved_search_register'));
});

View file

@ -0,0 +1,5 @@
define(function (require) {
return function savedSearchObjectFn(savedSearches) {
return savedSearches;
};
});

View file

@ -25,6 +25,12 @@ define(function (require) {
this.type = SavedSearch.type;
this.Class = SavedSearch;
this.loaderProperties = {
name: 'searches',
noun: 'Saved Search',
nouns: 'saved searches'
};
this.get = function (id) {
return (new SavedSearch(id)).init();
};

View file

@ -19,7 +19,7 @@
<i aria-hidden="true" class="fa fa-chain-broken"></i> Unlinked!
</div>
<form ng-if="vis.type.requiresSearch && $state.linked" class="inline-form" name="queryInput">
<form ng-if="vis.type.requiresSearch && $state.linked" class="inline-form fill" name="queryInput">
<div class="typeahead">
<div class="input-group">
<input
@ -39,7 +39,7 @@
<form
ng-if="vis.type.requiresSearch && !$state.linked"
ng-submit="fetch()"
class="inline-form"
class="inline-form fill"
name="queryInput">
<div class="typeahead" kbn-typeahead="visualize">
<div class="input-group"

View file

@ -23,4 +23,8 @@ define(function (require) {
require('plugins/kibana/visualize/editor/vis_options');
require('plugins/kibana/visualize/saved_visualizations/_saved_vis');
require('plugins/kibana/visualize/saved_visualizations/saved_visualizations');
require('ui/saved_objects/saved_object_registry')
.register(require('plugins/kibana/visualize/saved_visualizations/saved_visualization_register'));
});

View file

@ -0,0 +1,5 @@
define(function (require) {
return function savedVisualizationFn(savedVisualizations) {
return savedVisualizations;
};
});

View file

@ -20,6 +20,12 @@ define(function (require) {
this.type = SavedVis.type;
this.Class = SavedVis;
this.loaderProperties = {
name: 'visualizations',
noun: 'Visualization',
nouns: 'visualizations'
};
this.get = function (id) {
return (new SavedVis(id)).init();
};

View file

@ -56,4 +56,4 @@
}
@import "../editor/styles/.editor.less";
@import "../editor/styles/_editor.less";

View file

@ -92,7 +92,7 @@ module.exports = Joi.object({
otherwise: Joi.default(false)
}),
lazyPort: Joi.number().default(5602),
lazyHost: Joi.string().hostname().default('0.0.0.0'),
lazyHost: Joi.string().hostname().default('localhost'),
lazyPrebuild: Joi.boolean().default(false),
lazyProxyTimeout: Joi.number().default(5 * 60000),
unsafeCache: Joi

View file

@ -28,13 +28,13 @@ class UiApp {
}
getModules() {
return _([
return _.chain([
this.autoloadOverrides || autoload.require,
this.uiExports.find(_.get(this, 'spec.uses', [])),
])
.flatten()
.uniq()
.push(this.main)
.unshift(this.main)
.value();
}

View file

@ -6,7 +6,14 @@ let fromRoot = require('../utils/fromRoot');
let asRegExp = flow(
escapeRegExp,
function (path) {
return path + '(?:\\.js)?$';
let last = path.slice(-1);
if (last === '/' || last === '\\') {
// match a directory explicitly
return path + '.*';
} else {
// match a directory or files or just the absolute path
return path + '(?:\\.js$|$|\\\\|\\/)?';
}
},
RegExp
);
@ -129,7 +136,7 @@ module.exports = class UiBundlerEnv {
if (exports) loader.push(`exports?${exports}`);
if (expose) loader.push(`expose?${expose}`);
if (loader.length) this.loaders.push({ test: asRegExp(path), loader: loader.join('!') });
if (!parse) this.noParse.push(asRegExp(path));
if (!parse) this.addNoParse(path);
}
claim(id, pluginId) {

View file

@ -11,7 +11,7 @@ var AggConfigs;
var indexPattern;
var buildHierarchicalData;
describe('buildHierarchicalData()', function () {
describe('buildHierarchicalData', function () {
beforeEach(ngMock.module('kibana'));
beforeEach(ngMock.inject(function (Private, $injector) {
@ -43,14 +43,15 @@ describe('buildHierarchicalData()', function () {
});
it('should set the slices with one children with the name _all', function () {
it('should set the slices with one child to a consistent label', function () {
var checkLabel = 'Count';
expect(results).to.have.property('slices');
expect(results.slices).to.have.property('children');
expect(results.slices.children).to.have.length(1);
expect(results.slices.children[0]).to.have.property('name', '_all');
expect(results.slices.children[0]).to.have.property('name', checkLabel);
expect(results.slices.children[0]).to.have.property('size', 412032);
expect(results).to.have.property('names');
expect(results.names).to.eql(['_all']);
expect(results.names).to.eql([checkLabel]);
expect(results).to.have.property('raw');
expect(results.raw).to.have.property('rows');
expect(results.raw.rows).to.have.length(1);
@ -222,7 +223,10 @@ describe('buildHierarchicalData()', function () {
type: 'pie',
aggs: [
{ type: 'count', schema: 'metric' },
{ type: 'filters', schema: 'segment', params: {
{
type: 'filters',
schema: 'segment',
params: {
filters: [
{ input: { query: { query_string: { query: '_type:apache' } } } },
{ input: { query: { query_string: { query: '_type:nginx' } } } }
@ -255,7 +259,10 @@ describe('buildHierarchicalData()', function () {
type: 'pie',
aggs: [
{ type: 'count', schema: 'metric' },
{ type: 'filters', schema: 'split', params: {
{
type: 'filters',
schema: 'split',
params: {
filters: [
{ input: { query: { query_string: { query: '_type:apache' } } } },
{ input: { query: { query_string: { query: '_type:nginx' } } } }

View file

@ -31,6 +31,7 @@ define(function (require) {
// If buckets is falsy then we should just return the aggs
if (!buckets) {
var label = 'Count';
var value = resp.aggregations
&& resp.aggregations[metric.id]
&& resp.aggregations[metric.id].value
@ -38,11 +39,11 @@ define(function (require) {
return {
hits: resp.hits.total,
raw: raw,
names: ['_all'],
names: [label],
tooltipFormatter: tooltipFormatter(raw.columns),
slices: {
children: [
{ name: '_all', size: value }
{ name: label, size: value }
]
}
};

View file

@ -0,0 +1,25 @@
module.exports = function () {
const id = Symbol('id');
class RangeKey {
constructor(bucket) {
this.gte = bucket.from == null ? -Infinity : bucket.from;
this.lt = bucket.to == null ? +Infinity : bucket.to;
this[id] = RangeKey.idBucket(bucket);
}
static idBucket(bucket) {
return `from:${bucket.from},to:${bucket.to}`;
}
toString() {
return this[id];
}
}
return RangeKey;
};

View file

@ -2,7 +2,12 @@ define(function (require) {
var buildRangeFilter = require('ui/filter_manager/lib/range');
return function createRangeFilterProvider(Private) {
return function (aggConfig, key) {
return buildRangeFilter(aggConfig.params.field, key, aggConfig.vis.indexPattern);
return buildRangeFilter(
aggConfig.params.field,
key,
aggConfig.vis.indexPattern,
aggConfig.fieldFormatter()(key)
);
};
};
});

View file

@ -4,7 +4,10 @@ define(function (require) {
var BucketAggType = Private(require('ui/agg_types/buckets/_bucket_agg_type'));
var createFilter = Private(require('ui/agg_types/buckets/create_filter/range'));
var FieldFormat = Private(require('ui/index_patterns/_field_format/FieldFormat'));
var RangeKey = Private(require('./RangeKey'));
var keyCaches = new WeakMap();
var formats = new WeakMap();
return new BucketAggType({
name: 'range',
@ -14,22 +17,36 @@ define(function (require) {
return aggConfig.params.field.displayName + ' ranges';
},
getKey: function (bucket, key, agg) {
let range = { gte: bucket.from, lt: bucket.to };
var keys = keyCaches.get(agg);
if (range.gte == null) range.gte = -Infinity;
if (range.lt == null) range.lt = +Infinity;
if (!keys) {
keys = new Map();
keyCaches.set(agg, keys);
}
return range;
var id = RangeKey.idBucket(bucket);
var key = keys.get(id);
if (!key) {
key = new RangeKey(bucket);
keys.set(id, key);
}
return key;
},
getFormat: function (agg) {
if (agg.$$rangeAggTypeFormat) return agg.$$rangeAggTypeFormat;
let format = formats.get(agg);
if (format) return format;
var RangeFormat = FieldFormat.from(function (range) {
var format = agg.fieldOwnFormatter();
let RangeFormat = FieldFormat.from(function (range) {
let format = agg.fieldOwnFormatter();
return `${format(range.gte)} to ${format(range.lt)}`;
});
return (this.$$rangeAggTypeFormat = new RangeFormat());
format = new RangeFormat();
formats.set(agg, format);
return format;
},
params: [
{

View file

@ -22,7 +22,7 @@ module.exports = function (chrome, internals) {
}()))
.directive('kbnChrome', function ($rootScope) {
return {
compile: function ($el) {
template: function ($el) {
var $content = $(require('ui/chrome/chrome.html'));
var $app = $content.find('.application');
@ -35,7 +35,7 @@ module.exports = function (chrome, internals) {
$app.html(internals.rootTemplate);
}
$el.html($content);
return $content;
},
controllerAs: 'chrome',
controller: function ($scope, $rootScope, $location, $http) {

View file

@ -1,5 +1,5 @@
<kbn-notifications list="notifList"></kbn-notifications>
<div class="content" style="display: none;" chrome-context >
<div class="content" chrome-context >
<nav
ng-style="{ background: chrome.getNavBackground() }"
ng-class="{ show: chrome.getVisible() }"

View file

@ -1,3 +1,5 @@
require('babel/polyfill');
var _ = require('lodash');
var $ = require('jquery');
var angular = require('angular');
@ -40,7 +42,6 @@ require('./api/theme')(chrome, internals);
chrome.bootstrap = function () {
chrome.setupAngular();
angular.bootstrap(document, ['kibana']);
$(document.body).children(':not(style-compile)').show();
};
module.exports = chrome;

View file

@ -4,28 +4,9 @@ define(function (require) {
var rison = require('ui/utils/rison');
var keymap = require('ui/utils/key_map');
module.directive('savedObjectFinder', function (savedSearches, savedVisualizations, savedDashboards, $location, kbnUrl) {
module.directive('savedObjectFinder', function ($location, $injector, kbnUrl, Private) {
var types = {
searches: {
service: savedSearches,
name: 'searches',
noun: 'Saved Search',
nouns: 'saved searches'
},
visualizations: {
service: savedVisualizations,
name: 'visualizations',
noun: 'Visualization',
nouns: 'visualizations'
},
dashboards: {
service: savedDashboards,
name: 'dashboards',
noun: 'Dashboard',
nouns: 'dashboards'
}
};
var services = Private(require('ui/saved_objects/saved_object_registry')).byLoaderPropertiesName;
return {
restrict: 'E',
@ -54,13 +35,11 @@ define(function (require) {
// the most recently entered search/filter
var prevSearch;
// the service we will use to find records
var service;
// the list of hits, used to render display
self.hits = [];
self.objectType = types[$scope.type];
self.service = services[$scope.type];
self.properties = self.service.loaderProperties;
filterResults();
@ -230,7 +209,7 @@ define(function (require) {
};
self.hitCountNoun = function () {
return ((self.hitCount === 1) ? self.objectType.noun : self.objectType.nouns).toLowerCase();
return ((self.hitCount === 1) ? self.properties.noun : self.properties.nouns).toLowerCase();
};
function selectTopHit() {
@ -241,8 +220,8 @@ define(function (require) {
}
function filterResults() {
if (!self.objectType) return;
if (!self.objectType.service) return;
if (!self.service) return;
if (!self.properties) return;
// track the filter that we use for this search,
// but ensure that we don't search for the same
@ -252,7 +231,7 @@ define(function (require) {
if (prevSearch === filter) return;
prevSearch = filter;
self.objectType.service.find(filter)
self.service.find(filter)
.then(function (hits) {
// ensure that we don't display old results
// as we can't really cancel requests

View file

@ -1,7 +1,8 @@
define(function (require) {
var _ = require('lodash');
var Notifier = require('ui/notify/Notifier');
return function EventsProvider(Private, Promise, Notifier) {
return function EventsProvider(Private, Promise) {
var SimpleEmitter = require('ui/utils/SimpleEmitter');
var notify = new Notifier({ location: 'EventEmitter' });

View file

@ -10,8 +10,14 @@ define(function () {
.get(filter.meta.index).then(function (indexPattern) {
key = filter.meta.field;
field = indexPattern.fields.byName[key];
value = filter.script.params.value;
value = field.format.convert(value);
if (filter.meta.formattedValue) {
value = filter.meta.formattedValue;
} else {
value = filter.script.params.value;
value = field.format.convert(value);
}
return { key: key, value: value };
});
}

View file

@ -1,7 +1,10 @@
define(function (require) {
var _ = require('lodash');
return function buildRangeFilter(field, params, indexPattern) {
var filter = { meta: { index: indexPattern.id} };
return function buildRangeFilter(field, params, indexPattern, formattedValue) {
var filter = { meta: { index: indexPattern.id } };
if (formattedValue) filter.meta.formattedValue = formattedValue;
params = _.clone(params);
if (params.gte && params.gt) throw new Error('gte and gt are mutually exclusive');
if (params.lte && params.lt) throw new Error('lte and lt are mutually exclusive');

View file

@ -1,13 +1,13 @@
<form role="form">
<div class="form-group finder-form">
<div class="finder-form-options">
<a class="small" ng-click="finder.manageObjects(finder.objectType.name)">manage {{finder.objectType.name}}</a>
<a class="small" ng-click="finder.manageObjects(finder.properties.name)">manage {{finder.properties.nouns}}</a>
</div>
<div class="clearfix visible-xs-block"></div>
<input
input-focus
ng-model="filter"
ng-attr-placeholder="{{finder.objectType.noun}} Filter"
ng-attr-placeholder="{{finder.properties.noun}} Filter"
ng-keydown="finder.filterKeyDown($event)"
class="form-control"
name="filter"
@ -40,7 +40,7 @@
<li
class="list-group-item list-group-no-results"
ng-if="finder.hits.length === 0">
<p ng-bind="'No matching ' + finder.objectType.nouns + ' found.'"></p>
<p ng-bind="'No matching ' + finder.properties.nouns + ' found.'"></p>
</li>
</ul>
</paginate>

View file

@ -0,0 +1,7 @@
define(function (require) {
return require('ui/registry/_registry')({
name: 'savedObjects',
index: ['loaderProperties.name'],
order: ['loaderProperties.name']
});
});

View file

@ -23,11 +23,6 @@
}
}
// the element should take up an even share of available space
> .fill {
flex: 1 1 1%;
}
button {
padding: @padding-base-vertical @padding-base-horizontal;
font-size: @font-size-base;
@ -79,7 +74,7 @@
}
.inline-form {
.flex-parent();
.flex-parent(0, 0, auto);
display: flex;
> .typeahead {
@ -102,6 +97,11 @@
}
}
}
// the element should take up an even share of available space
> .fill {
flex: 1 1 1%;
}
}
.nav-controls .column {

View file

@ -16,12 +16,13 @@ define(function (require) {
throw new Error('OrderedXKeysUtilService expects an object');
}
var objKeys = getUniqKeys(obj);
var uniqKeys = getUniqKeys(obj);
var uniqKeysPairs = [...uniqKeys.entries()];
var interval = _.get(obj, 'ordered.interval');
var dateInterval = moment.isDuration(interval) ? interval : false;
return _(objKeys)
.pairs()
return _(uniqKeysPairs)
.sortBy(function (d) {
if (d[1].isDate || d[1].isOrdered) {
return +d[0];

View file

@ -17,7 +17,7 @@ define(function (require) {
}
var flattenedData = flattenDataArray(obj);
var uniqueXValues = {};
var uniqueXValues = new Map();
var charts;
if (!obj.series) {
@ -36,7 +36,7 @@ define(function (require) {
flattenedData.forEach(function (d, i) {
var key = d.x;
var prev = uniqueXValues[key];
var prev = uniqueXValues.get(key);
if (d.xi != null) {
i = d.xi;
@ -46,12 +46,12 @@ define(function (require) {
i = Math.min(i, prev.index);
}
uniqueXValues[key] = {
uniqueXValues.set(key, {
index: i,
isDate: isDate,
isOrdered: isOrdered,
isNumber: _.isNumber(key)
};
});
});
return uniqueXValues;

View file

@ -517,8 +517,12 @@ define(function (require) {
var names = [];
var self = this;
_.forEach(array, function (obj) {
names.push({ label: obj.name, values: obj, index: index });
_.forEach(array, function (obj, i) {
names.push({
label: obj.name,
values: obj,
index: index
});
if (obj.children) {
var plusIndex = index + 1;

View file

@ -167,7 +167,7 @@ define(function (require) {
return pointLabel !== label.toString();
}
if (label && label !== '_all') {
if (label && label !== 'Count') {
d3.select(this).style('cursor', 'pointer');
}
@ -208,7 +208,7 @@ define(function (require) {
legendDiv.selectAll('li.color').each(function (d) {
var label = d.label;
if (label !== undefined && label !== '_all') {
if (label !== undefined && label !== 'Count') {
d3.select(this).call(self.events.addClickEvent());
}
});

View file

@ -1,26 +0,0 @@
module.exports = function (grunt) {
grunt.registerTask('build', [
'get_build_props',
'clean:target',
'clean:build',
'less:build',
'copy:kibana_src',
'clean:noDistPlugins',
'webpack:build',
'clean:unneeded_source_in_build',
'copy:dist',
'dist_readme',
'dist_package_json',
'chmod_kibana',
'make_plugin_dir',
'copy:plugin_readme',
'clean:test_from_node_modules',
'download_node_binaries',
'copy:versioned_dist',
'create_services',
'create_packages',
'create_shasums'
]);
};

39
tasks/build/archives.js Normal file
View file

@ -0,0 +1,39 @@
module.exports = function createPackages(grunt) {
let { config } = grunt;
let { resolve } = require('path');
let { execFile } = require('child_process');
let { all, fromNode } = require('bluebird');
let buildPath = resolve(config.get('root'), 'build');
let exec = async (cmd, args) => {
grunt.log.writeln(` > ${cmd} ${args.join(' ')}`);
await fromNode(cb => execFile(cmd, args, { cwd: buildPath }, cb));
};
let archives = async (platform) => {
// kibana.tar.gz
await exec('tar', ['-zchf', platform.tarPath, platform.buildName]);
// kibana.zip
if (/windows/.test(platform.name)) {
await exec('zip', ['-rq', '-ll', platform.zipPath, platform.buildName]);
} else {
await exec('zip', ['-rq', platform.zipPath, platform.buildName]);
}
};
grunt.registerTask('_build:archives', function () {
all(
grunt.config.get('platforms')
.map(async platform => {
grunt.file.mkdir('target');
await archives(platform);
})
)
.nodeify(this.async());
});
};

13
tasks/build/cliIndex.js Normal file
View file

@ -0,0 +1,13 @@
module.exports = function (grunt) {
var srcFile = 'build/kibana/src/cli/index.js';
var buildFile = 'build/kibana/src/cli/index.build.js';
var rename = require('fs').renameSync;
var unlink = require('fs').unlinkSync;
grunt.registerTask('_build:cliIndex', function () {
unlink(srcFile);
rename(buildFile, srcFile);
});
};

View file

@ -0,0 +1,85 @@
module.exports = function (grunt) {
let { map, fromNode } = require('bluebird');
let { resolve } = require('path');
let { pluck } = require('lodash');
let { createWriteStream } = require('fs');
let { createGunzip } = require('zlib');
let { Extract } = require('tar');
let { rename } = require('fs');
let wreck = require('wreck');
let platforms = grunt.config.get('platforms');
let activeDownloads = [];
let start = async (platform) => {
let finalDir = platform.nodeDir;
let downloadDir = `${finalDir}.temp`;
if (grunt.file.isDir(platform.nodeDir)) {
grunt.log.ok(`${platform.name} exists`);
return;
}
let resp = await fromNode(cb => {
let req = wreck.request('GET', platform.nodeUrl, null, function (err, resp) {
if (err) {
return cb(err);
}
if (resp.statusCode !== 200) {
return cb(new Error(`${platform.nodeUrl} failed with a ${resp.statusCode} response`));
}
return cb(null, resp);
});
});
// use an async iife to store promise for download
// then store platform in active downloads list
// which we will read from in the finish task
platform.downloadPromise = (async () => {
grunt.file.mkdir(downloadDir);
if (platform.name === 'windows') {
await fromNode(cb => {
resp
.pipe(createWriteStream(resolve(downloadDir, 'node.exe')))
.on('error', cb)
.on('finish', cb);
});
} else {
await fromNode(cb => {
resp
.pipe(createGunzip())
.on('error', cb)
.pipe(new Extract({ path: downloadDir, strip: 1 }))
.on('error', cb)
.on('end', cb);
});
}
await fromNode(cb => {
rename(downloadDir, finalDir, cb);
});
}());
activeDownloads.push(platform);
var bytes = parseInt(resp.headers['content-length'], 10) || 'unknown number of';
var mb = ((bytes / 1024) / 1024).toFixed(2);
grunt.log.ok(`downloading ${platform.name} - ${mb} mb`);
};
grunt.registerTask('_build:downloadNodes:start', function () {
map(platforms, start).nodeify(this.async());
});
grunt.registerTask('_build:downloadNodes:finish', function () {
map(activeDownloads, async (platform) => {
await platform.downloadPromise;
grunt.log.ok(`${platform.name} download complete`);
})
.nodeify(this.async());
});
};

View file

@ -1,7 +1,7 @@
module.exports = function (grunt) {
var exec = require('child_process').execSync;
grunt.registerTask('get_build_props', function () {
grunt.registerTask('_build:getProps', function () {
grunt.config.set('buildSha', String(exec('git rev-parse HEAD')).trim());
grunt.config.set('buildNum', parseFloat(exec('git log --format="%h" | wc -l')).trim());
grunt.config.set('buildNum', parseFloat(String(exec('git log --format="%h" | wc -l')).trim()));
});
};

30
tasks/build/index.js Normal file
View file

@ -0,0 +1,30 @@
module.exports = function (grunt) {
let { flatten } = require('lodash');
grunt.registerTask('build', flatten([
'_build:getProps',
'clean:build',
'clean:target',
'_build:downloadNodes:start',
'copy:devSource',
'babel:build',
'_build:cliIndex',
'_build:installedPlugins',
'_build:packageJson',
'_build:readme',
'_build:installNpmDeps',
'clean:testsFromModules',
'clean:deepModuleBins',
'clean:deepModules',
'run:optimizeBuild',
'stop:optimizeBuild',
'_build:downloadNodes:finish',
'_build:versionedLinks',
'_build:archives',
!grunt.option('os-packages') ? [] : [
'_build:pleaseRun',
'_build:osPackages',
],
'_build:shasums'
]));
};

View file

@ -0,0 +1,14 @@
module.exports = function (grunt) {
var { exec } = require('child_process');
var { resolve } = require('path');
grunt.registerTask('_build:installNpmDeps', function () {
grunt.file.mkdir('build/kibana/node_modules');
exec('npm install --production --no-optional', {
cwd: grunt.config.process('<%= root %>/build/kibana')
}, this.async());
});
};

View file

@ -0,0 +1,5 @@
module.exports = function (grunt) {
grunt.registerTask('_build:installedPlugins', function () {
grunt.file.mkdir('build/kibana/installedPlugins');
});
};

50
tasks/build/osPackages.js Normal file
View file

@ -0,0 +1,50 @@
module.exports = function (grunt) {
let { resolve } = require('path');
let { indexBy } = require('lodash');
let { config } = grunt;
let exec = require('../utils/exec');
let targetDir = config.get('target');
let version = config.get('pkg.version');
let userScriptsDir = config.get('userScriptsDir');
let servicesByName = indexBy(config.get('services'), 'name');
grunt.registerTask('_build:osPackages', function () {
grunt.config.get('platforms').forEach(({ name, buildDir }) => {
// TODO(sissel): Check if `fpm` is available
let arch = /x64$/.test(name) ? 'x86_64' : 'i686';
let fpm = args => exec('fpm', args);
let args = [
'--force',
'--package', targetDir,
'-s', 'dir', // input type
'--name', 'kibana',
'--version', version,
'--after-install', resolve(userScriptsDir, 'installer.sh'),
'--after-remove', resolve(userScriptsDir, 'remover.sh'),
'--config-files', '/opt/kibana/config/kibana.yml'
];
let files = buildDir + '/=/opt/kibana';
grunt.file.mkdir(targetDir);
// kibana.rpm and kibana.deb
if (/linux-x(86|64)$/.test(name)) {
let sysv = servicesByName.sysv.outputDir + '/etc/=/etc/';
fpm(args.concat('-t', 'rpm', '-a', arch, '--rpm-os', 'linux', files, sysv));
fpm(args.concat('-t', 'deb', '-a', arch, files, sysv));
return;
}
// kibana.pkg
if (/darwin-x(86|64)$/.test(name)) {
let launchd = servicesByName.launchd.outputDir + '/=/';
fpm(args.concat('-t', 'osxpkg', '-a', arch, files, launchd));
return;
}
});
});
};

View file

@ -0,0 +1,25 @@
module.exports = function (grunt) {
let { defaults } = require('lodash');
let pkg = grunt.config.get('pkg');
let deepModules = grunt.config.get('deepModules');
grunt.registerTask('_build:packageJson', function () {
grunt.file.write(
'build/kibana/package.json',
JSON.stringify({
name: pkg.name,
description: pkg.description,
keywords: pkg.keywords,
version: pkg.version,
build: {
number: grunt.config.get('buildNum'),
sha: grunt.config.get('buildSha')
},
repository: pkg.repository,
dependencies: defaults({}, pkg.dependencies, deepModules)
}, null, ' ')
);
});
};

30
tasks/build/pleaserun.js Normal file
View file

@ -0,0 +1,30 @@
module.exports = function createServices(grunt) {
var { resolve } = require('path');
let exec = require('../utils/exec');
let userScriptsPath = grunt.config.get('userScriptsPath');
grunt.registerTask('_build:pleaseRun', function () {
// TODO(sissel): Detect if 'pleaserun' is found, and provide a useful error
// to the user if it is missing.
grunt.config.get('services').forEach(function (service) {
grunt.file.mkdir(service.outputDir);
exec('pleaserun', [
'--install',
'--no-install-actions',
'--install-prefix', service.outputDir,
'--overwrite',
'--user', 'kibana',
'--sysv-log-path', '/var/log/kibana/',
'-p', service.name,
'-v', service.version,
'/opt/kibana/bin/kibana'
]);
});
grunt.file.mkdir(userScriptsPath);
exec('please-manage-user', ['--output', userScriptsPath, 'kibana']);
});
};

37
tasks/build/readme.js Normal file
View file

@ -0,0 +1,37 @@
let marked = require('marked');
let Promise = require('bluebird');
let { join } = require('path');
let TextRenderer = require('marked-text-renderer');
let _ = require('lodash');
let fs = require('fs');
let { AllHtmlEntities } = require('html-entities');
let entities = new AllHtmlEntities();
TextRenderer.prototype.heading = function (text, level, raw) {
return '\n\n' + text + '\n' + _.map(text, function () { return '='; }).join('') + '\n';
};
module.exports = function (grunt) {
grunt.registerTask('_build:readme', function () {
let transform = function (input) {
let output = input.replace(/<\!\-\- [^\-]+ \-\->/g, '\n');
output = marked(output);
return entities.decode(output);
};
marked.setOptions({
renderer: new TextRenderer(),
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false
});
grunt.file.write('build/kibana/README.txt', transform(grunt.file.read('README.md')));
grunt.file.write('build/kibana/LICENSE.txt', transform(grunt.file.read('LICENSE.md')));
});
};

View file

@ -1,12 +1,9 @@
var childProcess = require('child_process');
var Promise = require('bluebird');
var fs = require('fs');
var readdir = Promise.promisify(fs.readdir);
var exec = Promise.promisify(childProcess.exec);
var _ = require('lodash');
module.exports = function (grunt) {
var { promisify } = require('bluebird');
var readdir = promisify(require('fs').readdir);
var exec = promisify(require('child_process').exec);
grunt.registerTask('create_shasums', function () {
module.exports = function (grunt) {
grunt.registerTask('_build:shasums', function () {
var targetDir = grunt.config.get('target');
readdir(targetDir)

View file

@ -0,0 +1,29 @@
module.exports = function (grunt) {
let { basename, resolve } = require('path');
let { forOwn } = require('lodash');
let exec = require('../utils/exec').silent;
grunt.registerTask('_build:versionedLinks', function () {
let rootPath = grunt.config.get('root');
let buildFiles = grunt.file.expand('build/kibana/{*,.*}')
.map(function (file) {
return resolve(rootPath, file);
});
let ln = (source, link) => exec('ln', ['-s', source, link]);
grunt.config.get('platforms').forEach(function (platform) {
grunt.file.mkdir(platform.buildDir);
// link all files at the root of the build
buildFiles.forEach(function (source) {
ln(source, resolve(platform.buildDir, basename(source)));
});
// link the node modules
ln(platform.nodeDir, resolve(platform.buildDir, 'node'));
});
});
};

19
tasks/config/babel.js Normal file
View file

@ -0,0 +1,19 @@
let { defaults } = require('lodash');
let babelOptions = require('requirefrom')('src')('optimize/babelOptions');
module.exports = {
build: {
options: defaults({
optional: ['runtime']
}, babelOptions),
src: [
'build/kibana/**/*.js',
'!**/public/**',
'!**/node_modules/**',
'!**/bower_components/**',
'!**/__tests__/**'
],
dest: '.',
expand: true
}
};

View file

@ -1,6 +1,10 @@
module.exports = function (grunt) {
let modules = Object.keys(grunt.config.get('deepModules'));
return {
build: '<%= build %>',
target: '<%= target %>'
build: 'build',
target: 'target',
testsFromModules: 'build/kibana/node_modules/**/*test*/**',
deepModuleBins: 'build/kibana/node_modules/*/node_modules/**/.bin/{' + modules.join(',') + '}',
deepModules: 'build/kibana/node_modules/*/node_modules/**/{' + modules.join(',') + '}/',
};
};

View file

@ -1,49 +0,0 @@
module.exports = function (grunt) {
var _ = require('lodash');
var archiveName = function (plugin) {
return '<%= target %>/<%= pkg.name %>-' + (plugin ? 'plugin-' : '') + '<%= pkg.version %>';
};
return _.mapValues({
build_zip: archiveName() + '.zip',
build_tarball: archiveName() + '.tar.gz',
plugin: archiveName(true) + '.tar.gz'
}, function (filename, task) {
return {
options: {
archive: filename
},
files: [
{
flatten: true,
src: '<%= build %>/dist/bin/kibana',
dest: '<%= pkg.name %>/bin/kibana',
mode: 755
},
{
flatten: true,
src: '<%= build %>/dist/bin/kibana.bat',
dest: '<%= pkg.name %>/bin/kibana.bat'
},
{
expand: true,
cwd: '<%= build %>/dist/config',
src: ['**/*'],
dest: '<%= pkg.name %>/config'
},
{
expand: true,
cwd: '<%= build %>/dist/lib',
src: ['**/*'],
dest: '<%= pkg.name %>/lib'
},
{
expand: true,
cwd: '<%= build %>/dist',
src: ['*.txt'],
dest: '<%= pkg.name %>'
}
]
};
});
};

View file

@ -1,122 +1,20 @@
module.exports = function (grunt) {
var version = grunt.config.get('pkg.version');
var platforms = grunt.config.get('platforms');
var config = {
kibana_src: {
expand: true,
cwd: '<%= app %>',
src: '**',
dest: '<%= build %>/src/'
},
server_src: {
files: [
{
src: '<%= root %>/package.json',
dest: '<%= build %>/kibana/package.json'
},
{
src: '<%= server %>/app.js',
dest: '<%= build %>/kibana/app.js'
},
{
src: '<%= server %>/index.js',
dest: '<%= build %>/kibana/index.js'
},
{
expand: true,
cwd: '<%= server %>/bin/',
src: '**',
dest: '<%= build %>/kibana/bin'
},
{
expand: true,
cwd: '<%= server %>/config/',
src: '*.yml',
dest: '<%= build %>/kibana/config'
},
{
expand: true,
cwd: '<%= server %>/lib/',
src: '**',
dest: '<%= build %>/kibana/lib'
},
{
expand: true,
cwd: '<%= server %>/plugins/',
src: '**',
dest: '<%= build %>/kibana/plugins'
},
{
expand: true,
cwd: '<%= server %>/routes/',
src: '**',
dest: '<%= build %>/kibana/routes'
},
{
expand: true,
cwd: '<%= server %>/views/',
src: '**',
dest: '<%= build %>/kibana/views'
}
]
},
dist: {
return {
devSource: {
options: { mode: true },
files: [
{
expand: true,
cwd: '<%= build %>/kibana',
src: '**',
dest: '<%= build %>/dist/kibana/src'
},
{
expand: true,
cwd: '<%= server %>/config/',
src: 'kibana.yml',
dest: '<%= build %>/dist/kibana/config/'
},
{
expand: true,
cwd: '<%= bowerComponentsDir %>/ace-builds/src-noconflict/',
src: 'worker-json.js',
dest: '<%= build %>/dist/kibana/src/public/'
}
]
src: [
'src/**',
'bin/**',
'config/kibana.yml',
'!src/**/__tests__/**',
'!src/testUtils/**',
'!src/fixtures/**',
'!src/plugins/devMode/**',
'!src/plugins/testsBundle/**',
'!src/cli/cluster/**',
],
dest: 'build/kibana',
expand: true
},
versioned_dist: {
options: { mode: true },
files: []
},
plugin_readme: {
files: [
{
src: '<%= build %>/kibana/public/plugins/README.txt',
dest: '<%= build %>/dist/kibana/plugins/README.txt'
}
]
}
};
platforms.forEach(function (platform) {
config.versioned_dist.files.push({
expand: true,
cwd: '<%= build %>/dist/kibana',
src: '**',
dest: '<%= build %>/dist/kibana-' + version + '-' + platform
});
config.versioned_dist.files.push({
expand: true,
cwd: '<%= root %>/.node_binaries/' + platform,
src: '**',
dest: '<%= build %>/dist/kibana-' + version + '-' + platform + '/node'
});
});
return config;
};

37
tasks/config/platforms.js Normal file
View file

@ -0,0 +1,37 @@
module.exports = function (grunt) {
let { resolve } = require('path');
let version = grunt.config.get('pkg.version');
let nodeVersion = grunt.config.get('nodeVersion');
let rootPath = grunt.config.get('root');
let baseUri = `https://iojs.org/dist/v${nodeVersion}`;
return [
'darwin-x64',
'linux-x64',
'linux-x86',
'windows'
].map(function (name) {
let win = name === 'windows';
let nodeUrl = win ? `${baseUri}/win-x86/iojs.exe` : `${baseUri}/iojs-v${nodeVersion}-${name}.tar.gz`;
let nodeDir = resolve(rootPath, `.node_binaries/${nodeVersion}/${name}`);
let buildName = `kibana-${version}-${name}`;
let buildDir = resolve(rootPath, `build/${buildName}`);
let tarName = `${buildName}.tar.gz`;
let tarPath = resolve(rootPath, `target/${tarName}`);
let zipName = `${buildName}.zip`;
let zipPath = resolve(rootPath, `target/${zipName}`);
return {
name, win,
nodeUrl, nodeDir,
buildName, buildDir,
tarName, tarPath,
zipName, zipPath,
};
});
};

View file

@ -17,6 +17,21 @@ module.exports = function (grunt) {
'--optimize.tests=true',
'--optimize.lazy=false'
]
},
optimizeBuild: {
options: {
wait: false,
ready: /Optimization .+ complete/,
quiet: true
},
cmd: './build/kibana/bin/kibana',
args: [
'--env.name=production',
'--logging.json=false',
'--plugins.initialize=false',
'--server.autoListen=false'
]
}
};

View file

@ -1,31 +1,27 @@
var createPackages = require('../create_packages');
var _ = require('lodash');
var getBaseNames = createPackages.getBaseNames;
module.exports = function (grunt) {
var upload = _(getBaseNames(grunt))
.map(function (basename) {
return [
basename + '.tar.gz',
basename + '.tar.gz.sha1.txt',
basename + '.zip',
basename + '.zip.sha1.txt'
];
})
.flattenDeep()
.map(function (filename) {
return {
src: 'target/' + filename,
dest: 'kibana/kibana/' + filename
};
})
.value();
var { config } = grunt;
return {
release: {
bucket: 'download.elasticsearch.org',
access: 'private',
// debug: true, // uncommment to prevent actual upload
upload: upload
debug: false,
upload: config.get('platforms')
.reduce(function (files, platform) {
return files.concat(
platform.tarName,
platform.tarName + '.sha1.txt',
platform.zipName,
platform.zipName + '.sha1.txt'
);
}, [])
.map(function (filename) {
return {
src: 'target/' + filename,
dest: 'kibana/kibana/' + filename
};
})
}
};
};

14
tasks/config/services.js Normal file
View file

@ -0,0 +1,14 @@
module.exports = function (grunt) {
let { resolve } = require('path');
let rootDir = grunt.config.get('root');
return [
['launchd', '10.9'],
['upstart', '1.5'],
['systemd', 'default'],
['sysv', 'lsb-3.1']
]
.map(function ([ name, version ]) {
return { name, version, outputDir: resolve(rootDir, `build/services/${name}`) };
});
};

View file

@ -1,76 +0,0 @@
/* eslint camelcase:0 */
var child_process = require('child_process');
var Promise = require('bluebird');
var { join } = require('path');
var mkdirp = Promise.promisifyAll(require('mkdirp'));
var execFile = Promise.promisify(child_process.execFile);
var getBaseNames = function (grunt) {
var packageName = grunt.config.get('pkg.name');
var version = grunt.config.get('pkg.version');
var platforms = grunt.config.get('platforms');
return platforms.map(function (platform) {
return packageName + '-' + version + '-' + platform;
});
};
function createPackages(grunt) {
grunt.registerTask('create_packages', function () {
var done = this.async();
var target = grunt.config.get('target');
var distPath = join(grunt.config.get('build'), 'dist');
var version = grunt.config.get('pkg.version');
var createPackage = function (name) {
var options = { cwd: distPath };
var archiveName = join(target, name);
var commands = [];
var arch = /x64$/.test(name) ? 'x86_64' : 'i686';
var fpm_options = [ 'fpm', '-f', '-p', target, '-s', 'dir', '-n', 'kibana', '-v', version,
'--after-install', join(distPath, 'user', 'installer.sh'),
'--after-remove', join(distPath, 'user', 'remover.sh'),
'--config-files', '/opt/kibana/config/kibana.yml' ];
var fpm_files = join(distPath, name) + '/=/opt/kibana';
// kibana.tar.gz
commands.push([ 'tar', '-zcf', archiveName + '.tar.gz', name ]);
// kibana.zip
if (/windows/.test(name)) {
commands.push([ 'zip', '-rq', '-ll', archiveName + '.zip', name ]);
} else {
commands.push([ 'zip', '-rq', archiveName + '.zip', name ]);
}
if (grunt.option('os-packages')) {
// TODO(sissel): Add before-install scripts to create kibana user
// TODO(sissel): Check if `fpm` is available
if (/linux-x(86|64)$/.test(name)) {
// kibana.rpm and kibana.deb
var sysv_init = join(distPath, 'services', 'sysv') + '/etc/=/etc/';
commands.push(fpm_options.concat(['-t', 'rpm', '-a', arch, '--rpm-os', 'linux', fpm_files, sysv_init]));
commands.push(fpm_options.concat(['-t', 'deb', '-a', arch, fpm_files, sysv_init]));
} else if (/darwin-x(86|64)$/.test(name)) {
// kibana.pkg
var launchd = join(distPath, 'services', 'launchd') + '/=/';
commands.push(fpm_options.concat(['-t', 'osxpkg', '-a', arch, fpm_files, launchd]));
}
}
return mkdirp.mkdirpAsync(target)
.then(function (arg) {
return Promise.map(commands, function (cmd) {
return execFile(cmd.shift(), cmd, options);
});
}, function (err) { console.log('Failure on ' + name + ': ' + err); });
};
Promise.map(getBaseNames(grunt), createPackage).finally(done);
});
}
module.exports = createPackages;
createPackages.getBaseNames = getBaseNames;

View file

@ -1,51 +0,0 @@
/* eslint camelcase:0 */
var childProcess = require('child_process');
var Promise = require('bluebird');
var { join } = require('path');
var mkdirp = Promise.promisifyAll(require('mkdirp'));
var execFile = Promise.promisify(childProcess.execFile);
function createServices(grunt) {
grunt.registerTask('create_services', function () {
var done = this.async();
var target = grunt.config.get('target');
var distPath = join(grunt.config.get('build'), 'dist');
var services = grunt.config.get('services');
var createService = function (arg) {
var service = arg[0];
var service_version = arg[1];
var options = { cwd: distPath };
var output = join(distPath, 'services', service);
var pleaserun_args = ['--install', '--no-install-actions',
'--install-prefix', output, '--overwrite',
'--user', 'kibana',
'--sysv-log-path', '/var/log/kibana/',
'-p', service, '-v', service_version,
'/opt/kibana/bin/kibana'];
return mkdirp.mkdirpAsync(target)
.then(function (arg) {
return execFile('pleaserun', pleaserun_args, options);
}, function (err) { console.log('pleaserun failed: ' + err + '. Args: ' + pleaserun_args.join(' ')); });
};
// TODO(sissel): Detect if 'pleaserun' is found, and provide a useful error
// to the user if it is missing.
mkdirp.mkdirpAsync(distPath)
.then(function () {
return Promise.map(services, createService);
})
.then(function (arg) {
// Create the user-management scripts
var output = join(distPath, 'user');
return mkdirp.mkdirpAsync(output).then(function () {
return execFile('please-manage-user', ['--output', output, 'kibana'], { cwd: distPath });
});
}, function (err) { console.log('please-manage-user failed: ' + err + '.'); })
.finally(done);
});
}
module.exports = createServices;

View file

@ -1,19 +0,0 @@
module.exports = function (grunt) {
grunt.registerTask('dist_package_json', function () {
var path = grunt.config.process('<%= build %>/kibana/package.json');
var pkg = grunt.config.get('pkg');
grunt.file.write(path, JSON.stringify({
name: pkg.name,
description: pkg.description,
keywords: pkg.keywords,
version: pkg.version,
build: {
number: grunt.config.get('buildNum'),
sha: grunt.config.get('buildSha')
},
repository: pkg.repository,
dependencies: pkg.dependencies
}, null, ' '));
});
};

View file

@ -1,61 +0,0 @@
var marked = require('marked');
var Promise = require('bluebird');
var { join } = require('path');
var TextRenderer = require('marked-text-renderer');
var _ = require('lodash');
var fs = require('fs');
var { AllHtmlEntities } = require('html-entities');
var entities = new AllHtmlEntities();
var readFile = Promise.promisify(fs.readFile);
var writeFile = Promise.promisify(fs.writeFile);
TextRenderer.prototype.heading = function (text, level, raw) {
return '\n\n' + text + '\n' + _.map(text, function () { return '='; }).join('') + '\n';
};
var process = function (input) {
var output = input.replace(/<\!\-\- [^\-]+ \-\->/g, '\n');
output = marked(output);
return entities.decode(output);
};
module.exports = function (grunt) {
grunt.registerTask('dist_readme', function () {
var done = this.async();
var root = grunt.config.get('root');
var build = grunt.config.get('build');
var srcReadme = join(root, 'README.md');
var distReadme = join(build, 'dist', 'kibana', 'README.txt');
var srcLicense = join(root, 'LICENSE.md');
var distLicense = join(build, 'dist', 'kibana', 'LICENSE.txt');
marked.setOptions({
renderer: new TextRenderer(),
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false
});
readFile(srcReadme, 'utf-8')
.then(function (data) {
return writeFile(distReadme, process(data.toString()));
})
.then(function () {
return readFile(srcLicense, 'utf-8');
})
.then(function (data) {
return writeFile(distLicense, process(data.toString()));
})
.then(done)
.catch(done);
});
};

View file

@ -1,65 +0,0 @@
var _ = require('lodash');
var zlib = require('zlib');
var tar = require('tar');
var request = require('request');
var mkdirp = require('mkdirp');
var fs = require('fs');
var { join } = require('path');
var filesPatern = _.template('node-v<%- version %>-<%- platform %>.tar.gz');
var urlPattern = _.template('http://nodejs.org/dist/v<%- version %>/<%- file %>');
var Promise = require('bluebird');
module.exports = function (grunt) {
grunt.registerTask('download_node_binaries', 'Download the node.js binaries', function () {
var platforms = _.without(grunt.config.get('platforms'), 'windows');
var rootPath = grunt.config.get('root');
var version = grunt.config.get('nodeVersion');
var handle404 = function (response) {
if (response.statusCode !== 200) {
throw new Error(response.request.href + ' failed with a ' + response.statusCode);
}
};
var downloadWindows = function (cb) {
return new Promise(function (resolve, reject) {
var dest = join(rootPath, '.node_binaries', 'windows');
fs.stat(dest, function (err) {
if (!err) return resolve(); // skip downloading if we already have them
var url = urlPattern({ version: version, file: 'node.exe'});
mkdirp(dest, function (err) {
if (err) return reject(err);
var out = fs.createWriteStream(join(dest, 'node.exe'));
out.on('close', resolve).on('error', reject);
var req = request.get(url);
req.on('response', handle404);
req.pipe(out);
});
});
});
};
var download = function (platform) {
return new Promise(function (resolve, reject) {
var dest = join(rootPath, '.node_binaries', platform);
fs.stat(dest, function (err) {
if (!err) return resolve(); // skip downloading if we already have them
var file = filesPatern({ version: version, platform: platform });
var url = urlPattern({ version: version, file: file });
mkdirp(dest, function (err) {
if (err) return reject(err);
var unzip = zlib.createGunzip();
var out = new tar.Extract({ path: dest, strip: 1 });
out.on('close', resolve).on('error', reject);
var req = request.get(url);
req.on('response', handle404);
req.pipe(unzip).pipe(out);
});
});
});
};
return Promise.map(platforms, download).then(downloadWindows).nodeify(this.async());
});
};

View file

@ -1,8 +1,10 @@
module.exports = function (grunt) {
let { compact } = require('lodash');
grunt.registerTask('jenkins', 'Jenkins build script', [
grunt.registerTask('jenkins', 'Jenkins build script', compact([
'esvm:dev',
'test'
]);
'test',
process.env.JOB_NAME === 'kibana_core' ? 'build' : null
]));
};

View file

@ -10,7 +10,7 @@ module.exports = function (grunt) {
var done = this.async();
var result = {};
var options = {start: process.cwd(), json: true };
var options = { start: process.cwd(), json: true };
var checkQueueLength = 2;
function processPackage(info, dependency) {

View file

@ -1,21 +0,0 @@
module.exports = function (grunt) {
var childProcess = require('child_process');
var { join } = require('path');
grunt.registerTask('npm_install_kibana', 'NPM install kibana server into dist', function () {
var done = this.async();
var cwd = join(grunt.config.get('build'), 'dist', 'kibana', 'src');
var command = 'npm install --production --no-optional';
var options = { cwd: cwd };
childProcess.exec(command, options, function (err, stdout, stderr) {
if (err) {
grunt.log.error(stderr);
return done(err);
}
grunt.log.writeln(stdout);
return done();
});
});
};

View file

@ -1,27 +0,0 @@
module.exports = function (grunt) {
grunt.registerTask('make_plugin_dir', function () {
var dir = grunt.config.process('<%= build %>/dist/kibana/plugins');
grunt.file.mkdir(dir);
});
grunt.registerTask('describe_bundled_plugins', function () {
var configKey = 'bundled_plugin_ids';
var file = grunt.config.process('<%= build %>/dist/kibana/config/kibana.yml');
var idList = grunt.config.get('bundled_plugin_module_ids').map(function (id) {
return ' - ' + id;
}).join('\n');
var contents = grunt.file.read(file);
if (contents.indexOf(configKey) !== -1) {
grunt.log.error('bundled plugin ids already written to config/kibana.yml');
return;
}
contents +=
'\n# Plugins that are included in the build, and no longer found in the plugins/ folder' +
'\n' + configKey + ':' +
'\n' + idList;
grunt.file.write(file, contents);
});
};

View file

@ -1,18 +1,51 @@
module.exports = function (grunt) {
var readline = require('readline');
// build, then zip and upload to s3
grunt.registerTask('release', [
'distribute:load_s3_config',
'_release:confirmUpload',
'_release:loadS3Config',
'build',
's3:release',
'_release:complete'
]);
grunt.registerTask('_release:confirmUpload', function () {
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('close', this.async());
rl.question('Do you want to actually upload the files to s3 after building?, [N/y] ', function (resp) {
var debug = resp.toLowerCase().trim()[0] !== 'y';
grunt.config.set('s3.release.debug', debug);
rl.close();
});
});
// collect the key and secret from the .aws-config.json file, finish configuring the s3 task
grunt.registerTask('distribute:load_s3_config', function () {
grunt.registerTask('_release:loadS3Config', function () {
var config = grunt.file.readJSON('.aws-config.json');
grunt.config('s3.options', {
key: config.key,
secret: config.secret
});
});
grunt.registerTask('_release:complete', function () {
grunt.log.ok('Builds released');
grunt.log.write(
`
${grunt.config.get('platforms').reduce((t, p) => {
return (
`${t}https://download.elastic.co/kibana/kibana/${p.buildName}.tar.gz
https://download.elastic.co/kibana/kibana/${p.buildName}.zip
`
);
}, '')}
`
);
});
};

26
tasks/utils/exec.js Normal file
View file

@ -0,0 +1,26 @@
let { execFileSync } = require('child_process');
function exec(cmd, args, opts) {
console.log(' >', cmd, args.join(' '));
exec.silent(cmd, args, opts);
};
exec.silent = function (cmd, args, opts) {
opts = opts || {};
if (!opts.stdio) opts.stdio = ['ignore', 1, 2];
try {
execFileSync(cmd, args, opts);
} catch (e) {
if (opts.stdio[1] !== 1) {
console.log(e.stdout + '');
}
if (opts.stdio[2] !== 2) {
console.log(e.stderr + '');
}
throw e;
}
};
module.exports = exec;