youtubebeat/vendor/github.com/elastic/beats/libbeat/dashboards/dashboards.go

227 lines
6.2 KiB
Go

// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package dashboards
import (
"context"
"errors"
"fmt"
"path/filepath"
"strconv"
"strings"
errw "github.com/pkg/errors"
"github.com/elastic/beats/libbeat/common"
)
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(
ctx context.Context,
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
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.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(ctx, hostname, kibanaConfig, &dashConfig, msgOutputter)
default:
return errors.New("Elasticsearch or Kibana configuration missing for loading dashboards.")
}
}
func setupAndImportDashboardsViaKibana(ctx context.Context, hostname string, kibanaConfig *common.Config,
dashboardsConfig *Config, msgOutputter MessageOutputter) error {
kibanaLoader, err := NewKibanaLoader(ctx, kibanaConfig, dashboardsConfig, hostname, msgOutputter)
if err != nil {
return fmt.Errorf("fail to create the Kibana loader: %v", err)
}
defer kibanaLoader.Close()
kibanaLoader.statusMsg("Kibana URL %v", kibanaLoader.client.Connection.URL)
return ImportDashboardsViaKibana(kibanaLoader)
}
func ImportDashboardsViaKibana(kibanaLoader *KibanaLoader) error {
if !isKibanaAPIavailable(kibanaLoader.version) {
return fmt.Errorf("Kibana API is not available in Kibana version %s", kibanaLoader.version)
}
version, err := common.NewVersion(kibanaLoader.version)
if err != nil {
return fmt.Errorf("Invalid Kibana version: %s", kibanaLoader.version)
}
importer, err := NewImporter(*version, kibanaLoader.config, kibanaLoader)
if err != nil {
return fmt.Errorf("fail to create a Kibana importer for loading the dashboards: %v", err)
}
if err := importer.Import(); err != nil {
return errw.Wrap(err, "fail to import the dashboards in Kibana")
}
return nil
}
func ImportDashboardsViaElasticsearch(esLoader *ElasticsearchLoader) error {
if err := esLoader.CreateKibanaIndex(); err != nil {
return fmt.Errorf("fail to create the kibana index: %v", err)
}
version, _ := common.NewVersion("5.0.0")
importer, err := NewImporter(*version, esLoader.config, esLoader)
if err != nil {
return fmt.Errorf("fail to create an Elasticsearch importer for loading the dashboards: %v", err)
}
if err := importer.Import(); err != nil {
return fmt.Errorf("fail to import the dashboards in Elasticsearch: %v", err)
}
return nil
}
func getMajorAndMinorVersion(version string) (int, int, error) {
fields := strings.Split(version, ".")
if len(fields) != 3 {
return 0, 0, fmt.Errorf("wrong version %s", version)
}
majorVersion := fields[0]
minorVersion := fields[1]
majorVersionInt, err := strconv.Atoi(majorVersion)
if err != nil {
return 0, 0, err
}
minorVersionInt, err := strconv.Atoi(minorVersion)
if err != nil {
return 0, 0, err
}
return majorVersionInt, minorVersionInt, nil
}
func isKibanaAPIavailable(version string) bool {
majorVersion, minorVersion, err := getMajorAndMinorVersion(version)
if err != nil {
return false
}
if majorVersion == 5 && minorVersion >= 6 {
return true
}
if majorVersion >= 6 {
return true
}
return false
}