mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Merge branch 'master' of github.com:elastic/kibana into apps/home
This commit is contained in:
commit
93c8ab9d97
15 changed files with 142 additions and 51 deletions
|
@ -6,12 +6,12 @@
|
|||
* <<load-balancing, Load Balancing Across Multiple Elasticsearch Nodes>>
|
||||
|
||||
How you deploy Kibana largely depends on your use case. If you are the only user,
|
||||
you can run Kibana on your local machine and configure it to point to whatever
|
||||
Elasticsearch instance you want to interact with. Conversely, if you have a large
|
||||
you can run Kibana on your local machine and configure it to point to whatever
|
||||
Elasticsearch instance you want to interact with. Conversely, if you have a large
|
||||
number of heavy Kibana users, you might need to load balance across multiple
|
||||
Kibana instances that are all connected to the same Elasticsearch instance.
|
||||
|
||||
While Kibana isn't terribly resource intensive, we still recommend running Kibana
|
||||
While Kibana isn't terribly resource intensive, we still recommend running Kibana
|
||||
separate from your Elasticsearch data or master nodes. To distribute Kibana
|
||||
traffic across the nodes in your Elasticsearch cluster, you can run Kibana
|
||||
and an Elasticsearch client node on the same machine. For more information, see
|
||||
|
@ -22,16 +22,16 @@ and an Elasticsearch client node on the same machine. For more information, see
|
|||
=== Configuring Kibana to Work with Shield
|
||||
If you are using Shield to authenticate Elasticsearch users, you need to provide
|
||||
the Kibana server with credentials so it can access the `.kibana` index and monitor
|
||||
the cluster.
|
||||
the cluster.
|
||||
|
||||
To configure credentials for the Kibana server:
|
||||
|
||||
. Assign the `kibana4_server` role to a user in Shield. For more information, see
|
||||
{shield}/_shield_with_kibana_4.html[Configuring a Role for the Kibana 4 Server]
|
||||
. Assign the `kibana4_server` role to a user in Shield. For more information, see
|
||||
{shield}/kibana.html#kibana4-server-role[Configuring a Role for the Kibana 4 Server]
|
||||
in the Shield documentation.
|
||||
|
||||
. Set the `kibana_elasticsearch_username` and
|
||||
`kibana_elasticsearch_password` properties in `kibana.yml` to specify the credentials
|
||||
`kibana_elasticsearch_password` properties in `kibana.yml` to specify the credentials
|
||||
of the user you assigned the `kibana4_server`
|
||||
role:
|
||||
+
|
||||
|
@ -42,19 +42,19 @@ kibana_elasticsearch_password: kibana4-password
|
|||
----
|
||||
|
||||
Kibana 4 users also need access to the `.kibana` index so they can save and load searches, visualizations, and dashboards.
|
||||
For more information, see {shield}/_shield_with_kibana_4.html#kibana4-roles[Configuring Roles for Kibana 4 Users] in
|
||||
For more information, see {shield}/kibana.html#kibana4-server-role[Configuring Roles for Kibana 4 Users] in
|
||||
the Shield documentation.
|
||||
|
||||
TIP: See <<kibana-dynamic-mapping, Kibana and Elasticsearch Dynamic Mapping>> for important information on Kibana and
|
||||
TIP: See <<kibana-dynamic-mapping, Kibana and Elasticsearch Dynamic Mapping>> for important information on Kibana and
|
||||
the dynamic mapping feature in Elasticsearch.
|
||||
|
||||
[float]
|
||||
[[enabling-ssl]]
|
||||
=== Enabling SSL
|
||||
Kibana supports SSL encryption for both client requests and the requests the Kibana server
|
||||
Kibana supports SSL encryption for both client requests and the requests the Kibana server
|
||||
sends to Elasticsearch.
|
||||
|
||||
To encrypt communications between the browser and the Kibana server, you configure the `ssl_key_file `and
|
||||
To encrypt communications between the browser and the Kibana server, you configure the `ssl_key_file `and
|
||||
`ssl_cert_file` properties in `kibana.yml`:
|
||||
|
||||
[source,text]
|
||||
|
@ -64,9 +64,9 @@ ssl_key_file: /path/to/your/server.key
|
|||
ssl_cert_file: /path/to/your/server.crt
|
||||
----
|
||||
|
||||
If you are using Shield or a proxy that provides an HTTPS endpoint for Elasticsearch,
|
||||
If you are using Shield or a proxy that provides an HTTPS endpoint for Elasticsearch,
|
||||
you can configure Kibana to access Elasticsearch via HTTPS so communications between
|
||||
the Kibana server and Elasticsearch are encrypted.
|
||||
the Kibana server and Elasticsearch are encrypted.
|
||||
|
||||
To do this, you specify the HTTPS
|
||||
protocol when you configure the Elasticsearch URL in `kibana.yml`:
|
||||
|
@ -89,29 +89,29 @@ ca: /path/to/your/ca/cacert.pem
|
|||
[float]
|
||||
[[controlling-access]]
|
||||
=== Controlling access
|
||||
You can use http://www.elastic.co/overview/shield/[Elasticsearch Shield]
|
||||
(Shield) to control what Elasticsearch data users can access through Kibana.
|
||||
Shield provides index-level access control. If a user isn't authorized to run
|
||||
the query that populates a Kibana visualization, the user just sees an empty
|
||||
visualization.
|
||||
You can use http://www.elastic.co/overview/shield/[Elasticsearch Shield]
|
||||
(Shield) to control what Elasticsearch data users can access through Kibana.
|
||||
Shield provides index-level access control. If a user isn't authorized to run
|
||||
the query that populates a Kibana visualization, the user just sees an empty
|
||||
visualization.
|
||||
|
||||
To configure access to Kibana using Shield, you create Shield roles
|
||||
for Kibana using the `kibana4` default role as a starting point. For more
|
||||
information, see http://www.elastic.co/guide/en/shield/current/_shield_with_kibana_4.html[Using Shield with Kibana 4].
|
||||
To configure access to Kibana using Shield, you create Shield roles
|
||||
for Kibana using the `kibana4` default role as a starting point. For more
|
||||
information, see {shield}/kibana.html#_using_kibana_4_with_shield[Shield with Kibana 4][Using Shield with Kibana 4].
|
||||
|
||||
[float]
|
||||
[[load-balancing]]
|
||||
=== Load Balancing Across Multiple Elasticsearch Nodes
|
||||
If you have multiple nodes in your Elasticsearch cluster, the easiest way to distribute Kibana requests
|
||||
across the nodes is to run an Elasticsearch _client_ node on the same machine as Kibana.
|
||||
across the nodes is to run an Elasticsearch _client_ node on the same machine as Kibana.
|
||||
Elasticsearch client nodes are essentially smart load balancers that are part of the cluster. They
|
||||
process incoming HTTP requests, redirect operations to the other nodes in the cluster as needed, and
|
||||
gather and return the results. For more information, see
|
||||
process incoming HTTP requests, redirect operations to the other nodes in the cluster as needed, and
|
||||
gather and return the results. For more information, see
|
||||
http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html[Node] in the Elasticsearch reference.
|
||||
|
||||
To use a local client node to load balance Kibana requests:
|
||||
|
||||
. Install Elasticsearch on the same machine as Kibana.
|
||||
. Install Elasticsearch on the same machine as Kibana.
|
||||
. Configure the node as a client node. In `elasticsearch.yml`, set both `node.data` and `node.master` to `false`:
|
||||
+
|
||||
--------
|
||||
|
@ -122,7 +122,7 @@ To use a local client node to load balance Kibana requests:
|
|||
node.master: false
|
||||
node.data: false
|
||||
--------
|
||||
. Configure the client node to join your Elasticsearch cluster. In `elasticsearch.yml`, set the `cluster.name` to the
|
||||
. Configure the client node to join your Elasticsearch cluster. In `elasticsearch.yml`, set the `cluster.name` to the
|
||||
name of your cluster.
|
||||
+
|
||||
--------
|
||||
|
|
|
@ -10,7 +10,7 @@ All you need is:
|
|||
** Which Elasticsearch indices you want to search.
|
||||
|
||||
NOTE: If your Elasticsearch installation is protected by http://www.elastic.co/overview/shield/[Shield] see
|
||||
{shield}/_shield_with_kibana_4.html[Shield with Kibana 4] for additional setup instructions.
|
||||
{shield}/kibana.html#_using_kibana_4_with_shield[Shield with Kibana 4] for additional setup instructions.
|
||||
|
||||
[float]
|
||||
[[install]]
|
||||
|
|
|
@ -67,7 +67,6 @@
|
|||
"good": "^6.2.0",
|
||||
"good-squeeze": "^2.1.0",
|
||||
"hapi": "^8.6.1",
|
||||
"http-auth": "^2.2.5",
|
||||
"imports-loader": "^0.6.4",
|
||||
"joi": "^6.4.3",
|
||||
"js-yaml": "^3.2.5",
|
||||
|
|
|
@ -60,7 +60,7 @@ dashboard-grid {
|
|||
.panel-heading {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
.display(flex);
|
||||
|
||||
div.btn-group {
|
||||
white-space: nowrap;
|
||||
|
@ -69,8 +69,13 @@ dashboard-grid {
|
|||
|
||||
.panel-title {
|
||||
font-size: inherit;
|
||||
|
||||
// flexbox fix for IE10
|
||||
// http://stackoverflow.com/questions/22008135/internet-explorer-10-does-not-apply-flexbox-on-inline-elements
|
||||
display: inline-block;
|
||||
|
||||
.ellipsis();
|
||||
flex: 1 1 0;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
a {
|
||||
|
|
|
@ -30,11 +30,11 @@ define(function (require) {
|
|||
|
||||
(function rebuildDefer() {
|
||||
listener.defer = Promise.defer();
|
||||
listener.resolved = listener.defer.promise.then(function (value) {
|
||||
listener.resolved = listener.defer.promise.then(function (args) {
|
||||
rebuildDefer();
|
||||
|
||||
// we ignore the completion of handlers, just watch for unhandled errors
|
||||
Promise.resolve(handler(value)).catch(notify.fatal);
|
||||
Promise.resolve(handler.apply(handler, args)).catch(notify.fatal);
|
||||
});
|
||||
}());
|
||||
|
||||
|
@ -74,8 +74,9 @@ define(function (require) {
|
|||
* @param {any} [value] - The value that will be passed to all event handlers.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
Events.prototype.emit = function (name, value) {
|
||||
Events.prototype.emit = function (name) {
|
||||
var self = this;
|
||||
var args = _.rest(arguments);
|
||||
|
||||
if (!self._listeners[name]) {
|
||||
return self._emitChain;
|
||||
|
@ -83,7 +84,7 @@ define(function (require) {
|
|||
|
||||
return Promise.map(self._listeners[name], function (listener) {
|
||||
return self._emitChain = self._emitChain.then(function () {
|
||||
listener.defer.resolve(value);
|
||||
listener.defer.resolve(args);
|
||||
return listener.resolved;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -42,7 +42,7 @@ define(function (require) {
|
|||
var fields = indexPattern.fields;
|
||||
var field = self.field.toActualField();
|
||||
|
||||
_.remove(fields, { name: field.name });
|
||||
fields.remove({ name: field.name });
|
||||
fields.push(field);
|
||||
|
||||
if (!self.selectedFormatId) {
|
||||
|
@ -62,7 +62,7 @@ define(function (require) {
|
|||
var indexPattern = self.indexPattern;
|
||||
var field = self.field;
|
||||
|
||||
_.remove(indexPattern.fields, { name: field.name });
|
||||
indexPattern.fields.remove({ name: field.name });
|
||||
return indexPattern.save()
|
||||
.then(function () {
|
||||
notify.info('Deleted Field "' + field.name + '"');
|
||||
|
|
|
@ -136,6 +136,19 @@ define(function (require) {
|
|||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Remove items from this based on a predicate
|
||||
* @param {function|object|string} predicate - the predicate used to decide what is removed
|
||||
* @param {object} context - this binding for predicate
|
||||
* @return {array} - the removed data
|
||||
*/
|
||||
IndexedArray.prototype.remove = function (predicate, context) {
|
||||
var out = _.remove(this, predicate, context);
|
||||
_.remove(this.raw, predicate, context);
|
||||
this._clearIndices();
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* provide a hook for the JSON serializer
|
||||
* @return {array} - a plain, vanilla array with our same data
|
||||
|
|
|
@ -36,20 +36,31 @@ define(function (require) {
|
|||
{ id: false, name: '- none -' },
|
||||
{ id: 'lower', name: 'Lower Case' },
|
||||
{ id: 'upper', name: 'Upper Case' },
|
||||
{ id: 'short', name: 'Short Dots' }
|
||||
{ id: 'short', name: 'Short Dots' },
|
||||
{ id: 'base64', name: 'Base64 Decode'}
|
||||
];
|
||||
|
||||
_String.sampleInputs = [
|
||||
'A Quick Brown Fox.',
|
||||
'com.organizations.project.ClassName',
|
||||
'hostname.net'
|
||||
'hostname.net',
|
||||
'SGVsbG8gd29ybGQ='
|
||||
];
|
||||
|
||||
_String.prototype._base64Decode = function (val) {
|
||||
try {
|
||||
return window.atob(val);
|
||||
} catch (e) {
|
||||
return _.asPrettyString(val);
|
||||
}
|
||||
};
|
||||
|
||||
_String.prototype._convert = function (val) {
|
||||
switch (this.param('transform')) {
|
||||
case 'lower': return String(val).toLowerCase();
|
||||
case 'upper': return String(val).toUpperCase();
|
||||
case 'short': return _.shortenDottedString(val);
|
||||
case 'base64': return this._base64Decode(val);
|
||||
default: return _.asPrettyString(val);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -22,7 +22,8 @@ define(function (require) {
|
|||
// track request so we can abort it if needed
|
||||
var request = {};
|
||||
|
||||
var errorElem = $('<i class="fa fa-ban input-error"></i>').hide();
|
||||
var errorElem = $('<i tooltip={{tooltipMsg}} class="fa fa-ban input-error"></i>').hide();
|
||||
$compile(errorElem)($scope);
|
||||
|
||||
var init = function () {
|
||||
elem.after(errorElem);
|
||||
|
@ -84,10 +85,7 @@ define(function (require) {
|
|||
msg = resp.body.error;
|
||||
}
|
||||
|
||||
errorElem.attr('tooltip', msg);
|
||||
|
||||
// Compile is needed for the tooltip
|
||||
$compile(errorElem)($scope);
|
||||
$scope.tooltipMsg = msg;
|
||||
errorElem.show();
|
||||
|
||||
return undefined;
|
||||
|
|
|
@ -84,12 +84,6 @@ define(function (require) {
|
|||
return buckets;
|
||||
},
|
||||
|
||||
remove: _.wrap(_.remove, function (remove, arr, predicate, cntx) {
|
||||
var out = remove.call(this, arr, predicate, cntx);
|
||||
if (arr._clearIndices) arr._clearIndices();
|
||||
return out;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Remove or add a value to an array based on it's presense in the
|
||||
* array initially.
|
||||
|
|
|
@ -43,7 +43,8 @@ module.exports = function (grunt) {
|
|||
'flatten@0.0.1': ['MIT'],
|
||||
'color-name@1.0.0': ['UNLICENSE'],
|
||||
'css-color-names@0.0.1': ['MIT'],
|
||||
'inherits@1.0.0': ['ISC']
|
||||
'inherits@1.0.0': ['ISC'],
|
||||
'jsonpointer@1.1.0': ['MIT']
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
19
test/unit/specs/components/stringify/_string.js
Normal file
19
test/unit/specs/components/stringify/_string.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
define(function (require) {
|
||||
return ['String Format', function () {
|
||||
var fieldFormats;
|
||||
|
||||
beforeEach(module('kibana'));
|
||||
beforeEach(inject(function (Private) {
|
||||
fieldFormats = Private(require('registry/field_formats'));
|
||||
}));
|
||||
|
||||
it('decode a base64 string', function () {
|
||||
var StringFormat = fieldFormats.getType('string');
|
||||
var string = new StringFormat({
|
||||
transform: 'base64'
|
||||
});
|
||||
expect(string.convert('Zm9vYmFy')).to.be('foobar');
|
||||
});
|
||||
|
||||
}];
|
||||
});
|
|
@ -3,6 +3,7 @@ define(function (require) {
|
|||
describe(require('specs/components/stringify/_conformance'));
|
||||
describe(require('specs/components/stringify/_ip'));
|
||||
describe(require('specs/components/stringify/_source'));
|
||||
describe(require('specs/components/stringify/_string'));
|
||||
describe(require('specs/components/stringify/_url'));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -164,6 +164,41 @@ define(function (require) {
|
|||
});
|
||||
});
|
||||
|
||||
it('should pass multiple arguments from the emitter', function () {
|
||||
var obj = new Events();
|
||||
var handler = sinon.stub();
|
||||
var payload = [
|
||||
'one',
|
||||
{ hello: 'tests' },
|
||||
null
|
||||
];
|
||||
|
||||
obj.on('test', handler);
|
||||
|
||||
return obj.emit('test', payload[0], payload[1], payload[2])
|
||||
.then(function () {
|
||||
expect(handler.callCount).to.be(1);
|
||||
expect(handler.calledWithExactly(payload[0], payload[1], payload[2])).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should preserve the scope of the handler', function () {
|
||||
var obj = new Events();
|
||||
var expected = 'some value';
|
||||
var testValue;
|
||||
|
||||
function handler(arg1, arg2) {
|
||||
testValue = this.getVal();
|
||||
}
|
||||
handler.getVal = _.constant(expected);
|
||||
|
||||
obj.on('test', handler);
|
||||
return obj.emit('test')
|
||||
.then(function () {
|
||||
expect(testValue).to.equal(expected);
|
||||
});
|
||||
});
|
||||
|
||||
it('should always emit in the same order', function () {
|
||||
var handler = sinon.stub();
|
||||
|
||||
|
|
|
@ -104,6 +104,20 @@ define(function (require) {
|
|||
expect(sumOfGroups).to.eql(expectedCount);
|
||||
});
|
||||
|
||||
it('removes items based on a predicate', function () {
|
||||
var reg = new IndexedArray({
|
||||
group: ['group'],
|
||||
order: ['id'],
|
||||
initialSet: users
|
||||
});
|
||||
|
||||
reg.remove({name: 'John'});
|
||||
|
||||
expect(_.eq(reg.raw, reg.slice(0))).to.be(true);
|
||||
expect(reg.length).to.be(3);
|
||||
expect(reg[0].name).to.be('Anon');
|
||||
});
|
||||
|
||||
it('updates indices after values are re-ordered', function () {
|
||||
var rawUsers = users.slice(0);
|
||||
|
||||
|
@ -137,4 +151,4 @@ define(function (require) {
|
|||
|
||||
require('specs/utils/indexed_array/_path_getter')();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue