Skip to content

Commit

Permalink
Dashboard loading improvements and fixes (#5686)
Browse files Browse the repository at this point in the history
* Dashboard loading improvements and fixes

- fix reference config: always_kibana -> setup.dashboards.always_kibana
- pass the beat its hostname instead of configured beat name (which by
  chance is the hostname by default)
- if always_kibana is set to true, don't check elasticsearch, but try to
  install via kibana only
- only reuse elasticsearch username/password if elasticsearch output is
  enabled

* Review updates
  • Loading branch information
Steffen Siering authored and kvch committed Nov 23, 2017
1 parent 74102eb commit 554701f
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 56 deletions.
5 changes: 3 additions & 2 deletions auditbeat/auditbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -722,8 +722,9 @@ output.elasticsearch:
# dashboards and index pattern. Example: testbeat-*
#setup.dashboards.index:

# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version
#always_kibana: false
# Always use the Kibana API for loading the dashboards instead of autodetecting
# how to install the dashboards by first querying Elasticsearch.
#setup.dashboards.always_kibana: false

#============================== Template =====================================

Expand Down
5 changes: 3 additions & 2 deletions filebeat/filebeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1167,8 +1167,9 @@ output.elasticsearch:
# dashboards and index pattern. Example: testbeat-*
#setup.dashboards.index:

# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version
#always_kibana: false
# Always use the Kibana API for loading the dashboards instead of autodetecting
# how to install the dashboards by first querying Elasticsearch.
#setup.dashboards.always_kibana: false

#============================== Template =====================================

Expand Down
5 changes: 3 additions & 2 deletions heartbeat/heartbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -842,8 +842,9 @@ output.elasticsearch:
# dashboards and index pattern. Example: testbeat-*
#setup.dashboards.index:

# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version
#always_kibana: false
# Always use the Kibana API for loading the dashboards instead of autodetecting
# how to install the dashboards by first querying Elasticsearch.
#setup.dashboards.always_kibana: false

#============================== Template =====================================

Expand Down
5 changes: 3 additions & 2 deletions libbeat/_meta/config.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -628,8 +628,9 @@ output.elasticsearch:
# dashboards and index pattern. Example: testbeat-*
#setup.dashboards.index:

# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version
#always_kibana: false
# Always use the Kibana API for loading the dashboards instead of autodetecting
# how to install the dashboards by first querying Elasticsearch.
#setup.dashboards.always_kibana: false

#============================== Template =====================================

Expand Down
4 changes: 2 additions & 2 deletions libbeat/cmd/instance/beat.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,13 +537,13 @@ func (b *Beat) loadDashboards(force bool) error {
}
}

if b.Config.Dashboards != nil && b.Config.Dashboards.Enabled() {
if b.Config.Dashboards.Enabled() {
var esConfig *common.Config

if b.Config.Output.Name() == "elasticsearch" {
esConfig = b.Config.Output.Config()
}
err := dashboards.ImportDashboards(b.Info.Beat, b.Info.Name, paths.Resolve(paths.Home, ""),
err := dashboards.ImportDashboards(b.Info.Beat, b.Info.Hostname, paths.Resolve(paths.Home, ""),
b.Config.Kibana, esConfig, b.Config.Dashboards, nil)
if err != nil {
return fmt.Errorf("Error importing Kibana dashboards: %v", err)
Expand Down
123 changes: 83 additions & 40 deletions libbeat/dashboards/dashboards.go
Original file line number Diff line number Diff line change
@@ -1,72 +1,115 @@
package dashboards

import (
"errors"
"fmt"
"path/filepath"
"strconv"
"strings"

"github.com/elastic/beats/libbeat/common"
"github.com/elastic/beats/libbeat/logp"
)

func ImportDashboards(beatName, hostname, homePath string,
kibanaConfig *common.Config, esConfig *common.Config,
dashboardsConfig *common.Config, msgOutputter MessageOutputter) error {
type importMethod uint8

// check import route
const (
importNone importMethod = iota
importViaKibana
importViaES
)

// ImportDashboards tries to import the kibana dashboards.
// If the Elastic Stack is at version 6.0+, the dashboards should be installed
// via the kibana dashboard loader plugin. For older versions of the Elastic Stack
// we write the dashboards directly into the .kibana index.
func ImportDashboards(
beatName, hostname, homePath string,
kibanaConfig, esConfig, dashboardsConfig *common.Config,
msgOutputter MessageOutputter,
) error {
if dashboardsConfig == nil || !dashboardsConfig.Enabled() {
return nil
}

// unpack dashboard config
dashConfig := defaultConfig
dashConfig.Beat = beatName
if dashConfig.Dir == "" {
dashConfig.Dir = filepath.Join(homePath, defaultDirectory)
}

dashConfig.Dir = filepath.Join(homePath, defaultDirectory)
err := dashboardsConfig.Unpack(&dashConfig)
if err != nil {
return err
}

// init kibana config object
if kibanaConfig == nil {
kibanaConfig = common.NewConfig()
}

if esConfig == nil && dashConfig.AlwaysKibana {
return setupAndImportDashboardsViaKibana(hostname, kibanaConfig, &dashConfig, msgOutputter)
}

esLoader, err := NewElasticsearchLoader(esConfig, &dashConfig, msgOutputter)
if err != nil {
return fmt.Errorf("fail to create the Elasticsearch loader: %v", err)
}
defer esLoader.Close()

esLoader.statusMsg("Elasticsearch URL %v", esLoader.client.Connection.URL)

majorVersion, _, err := getMajorAndMinorVersion(esLoader.version)
if err != nil {
return fmt.Errorf("wrong Elasticsearch version: %v", err)
}

if majorVersion < 6 {
if !kibanaConfig.HasField("host") {
// fallback to the beats hostname (localhost) if host is not configured
kibanaConfig.SetString("host", -1, hostname)
}
if esConfig.Enabled() {
username, _ := esConfig.String("username", -1)
password, _ := esConfig.String("password", -1)

if !kibanaConfig.HasField("username") && username != "" {
kibanaConfig.SetString("username", -1, username)
}
if !kibanaConfig.HasField("password") && password != "" {
kibanaConfig.SetString("password", -1, password)
}
}

var esLoader *ElasticsearchLoader

importVia := importNone
useKibana := importViaKibana
if !kibanaConfig.Enabled() {
useKibana = importNone
}

requiresKibana := dashConfig.AlwaysKibana || !esConfig.Enabled()
if requiresKibana {
importVia = useKibana
} else {
// Check import route via elasticsearch version. If Elasticsearch major
// version is >6, we assume Kibana also being at versions >6.0. In this
// case dashboards will be imported using the new kibana dashboard loader
// plugin.
// XXX(urso): Why do we test the Elasticsearch version? If kibana is
// configured, why not test the kibana version and plugin
// availability first?
esLoader, err = NewElasticsearchLoader(esConfig, &dashConfig, msgOutputter)
if err != nil {
return fmt.Errorf("fail to create the Elasticsearch loader: %v", err)
}
defer esLoader.Close()

esLoader.statusMsg("Elasticsearch URL %v", esLoader.client.Connection.URL)

majorVersion, _, err := getMajorAndMinorVersion(esLoader.version)
if err != nil {
return fmt.Errorf("wrong Elasticsearch version: %v", err)
}

if majorVersion < 6 {
importVia = importViaES
} else {
importVia = useKibana
}
}

// Try to import dashboards.
switch importVia {
case importViaES:
return ImportDashboardsViaElasticsearch(esLoader)
case importViaKibana:
return setupAndImportDashboardsViaKibana(hostname, kibanaConfig, &dashConfig, msgOutputter)
default:
return errors.New("Elasticsearch or Kibana configuration missing for loading dashboards.")
}

logp.Info("For Elasticsearch version >= 6.0.0, the Kibana dashboards need to be imported via the Kibana API.")

// In Cloud, the Kibana URL is different than the Elasticsearch URL,
// but the credentials are the same.
// So, by default, use same credentials for connecting to Kibana as to Elasticsearch
if !kibanaConfig.HasField("username") && len(esLoader.client.Username) > 0 {
kibanaConfig.SetString("username", -1, esLoader.client.Username)
}
if !kibanaConfig.HasField("password") && len(esLoader.client.Password) > 0 {
kibanaConfig.SetString("password", -1, esLoader.client.Password)
}

return setupAndImportDashboardsViaKibana(hostname, kibanaConfig, &dashConfig, msgOutputter)
}

func setupAndImportDashboardsViaKibana(hostname string, kibanaConfig *common.Config,
Expand Down
5 changes: 3 additions & 2 deletions metricbeat/metricbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1109,8 +1109,9 @@ output.elasticsearch:
# dashboards and index pattern. Example: testbeat-*
#setup.dashboards.index:

# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version
#always_kibana: false
# Always use the Kibana API for loading the dashboards instead of autodetecting
# how to install the dashboards by first querying Elasticsearch.
#setup.dashboards.always_kibana: false

#============================== Template =====================================

Expand Down
5 changes: 3 additions & 2 deletions packetbeat/packetbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1096,8 +1096,9 @@ output.elasticsearch:
# dashboards and index pattern. Example: testbeat-*
#setup.dashboards.index:

# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version
#always_kibana: false
# Always use the Kibana API for loading the dashboards instead of autodetecting
# how to install the dashboards by first querying Elasticsearch.
#setup.dashboards.always_kibana: false

#============================== Template =====================================

Expand Down
5 changes: 3 additions & 2 deletions winlogbeat/winlogbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -657,8 +657,9 @@ output.elasticsearch:
# dashboards and index pattern. Example: testbeat-*
#setup.dashboards.index:

# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version
#always_kibana: false
# Always use the Kibana API for loading the dashboards instead of autodetecting
# how to install the dashboards by first querying Elasticsearch.
#setup.dashboards.always_kibana: false

#============================== Template =====================================

Expand Down

0 comments on commit 554701f

Please sign in to comment.