Tech Topics

Kibana Plugin Developers meet Elasticsearch Clusters

In Kibana 5.2 we introduced the internal concept of clusters which, as a Kibana contributor or plugin author, will affect how you communicate with Elasticsearch. This change is transparent to the end-user and establishes the foundation for more features to come, beginning with Tribe support.

Prior to 5.2

Before 5.2, the Elasticsearch Kibana plugin provided two ways to communicate with your Elasticsearch cluster: you could either use the elasticsearch-js client directly or use callWithRequest.

elasticsearch-js client

The elasticsearch-js client provides an interface which is well-documented in the Quick Start section. It takes care of configuration and creation automatically, so using it is just a matter of calling a method which correlates to the Elasticsearch API.

Let’s see how that looks using Cluster Health as an example:

const { client } = server.plugins.elasticsearch;
client.cluster.health().then(response => {
  console.log(`cluster status is: #{response.status}`);
})

callWithRequest

The callWithRequest method ensures that the request is made in the context of the currently authenticated user. It uses the same underlying elasticsearch-js client, but requires a bit more configuration. You'll need to provide the request object, which can be obtained from the route handler, and you'll need to pass the API path as an argument instead of calling it directly.

Let’s see how the previous example looks now:

const { callWithRequest } = server.plugins.elasticsearch;
callWithRequest(request, 'cluster.health').then(response => {
  console.log(`cluster status is: #{response.status}`);
})

5.2 and beyond

In 5.2 we now have multiple clusters, and we need to specify one before making requests to Elasticsearch. Currently, there are two primary clusters; admin and data. The admin cluster contains the .kibana index and anything else used to persist state in Kibana. The data cluster contains all of the documents that you have indexed and would like to visualize.

To access one of the clusters, the Elasticsearch plugin provides getCluster. Let’s see how callWithRequest looks now:

const { callWithRequest } = server.plugins.elasticsearch.getCluster('data');
callWithRequest(request, 'cluster.health').then(response => {
  console.log(`cluster status is: #{response.status}`);
})

callWithInternalUser

In lieu of exposing the client directly, we now offer a method callWithInternalUser, and other than omitting the request argument it has the same interface as callWithRequest. It’s worth noting that in most situations you will want to use callWithRequest, because it ensures that the user has privileges to perform the action. callWithInternalUser is more appropriate for startup tasks and migrations, where the credentials specified within the kibana.yml are required. Should you still require the underlying client, you can obtain it by calling getClient on the cluster.

Let’s see how this looks:

const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('data');
callWithInternalUser('cluster.health').then(response => {
  console.log(`cluster status is: #{response.status}`);
})

Writing client-side Javascript?

If you're injecting the es service into your controllers or services and expect the data cluster, there are no changes necessary. If you're expecting the admin cluster, you'll want to use the esAdmin service.

What’s Next?

If you’re a plugin developer, you will likely need to make some changes for 5.2 compatibility. These changes should be transparent to the user and pave the way for improvements and features to come. If you have questions, reach out to us in #kibana or our forums. If you run into a bug, please file a GitHub Issue.