Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Kibana Spaces #8045

Merged
merged 12 commits into from
Oct 3, 2018
Merged
1 change: 1 addition & 0 deletions CHANGELOG-developer.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ The list below covers the major changes between 6.3.0 and master only.
`cmd.GenRootCmd`, `cmd.GenRootCmdWithRunFlags`, and `cmd.GenRootCmdWithIndexPrefixWithRunFlags`. {pull}7850[7850]
- Set current year in generator templates. {pull}8396[8396]
- You can now override default settings of libbeat by using instance.Settings. {pull}8449[8449]
- Add `-space-id` option to `export_dashboards.go` script to support Kibana Spaces {pull}7942[7942]
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ https://github.com/elastic/beats/compare/v6.4.0...master[Check the HEAD diff]
- Added the `add_process_metadata` processor to enrich events with process information. {pull}6789[6789]
- Report number of open file handles on Windows. {pull}8329[8329]
- Support for Kafka 2.0.0 in kafka output {pull}8399[8399]
- Add setting `setup.kibana.space.id` to support Kibana Spaces {pull}7942[7942]

*Auditbeat*

Expand Down
5 changes: 5 additions & 0 deletions auditbeat/auditbeat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ setup.kibana:
# IPv6 addresses should always be defined as: https://[2001:db8::1]:5601
#host: "localhost:5601"

# Kibana Space ID
# ID of the Kibana Space into which the dashboards should be loaded. By default,
# the Default Space will be used.
#space.id:

#============================= Elastic Cloud ==================================

# These settings simplify using auditbeat with the Elastic Cloud (https://cloud.elastic.co/).
Expand Down
11 changes: 8 additions & 3 deletions dev-tools/cmd/dashboards/export_dashboards.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"strings"

Expand All @@ -48,11 +49,14 @@ func makeURL(url, path string, params url.Values) string {
return strings.Join([]string{url, path, "?", params.Encode()}, "")
}

func Export(client *http.Client, conn string, dashboard string, out string) error {
func Export(client *http.Client, conn string, spaceID string, dashboard string, out string) error {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported function Export should have comment or be unexported

params := url.Values{}

params.Add("dashboard", dashboard)

if spaceID != "" {
exportAPI = path.Join("/s", spaceID, exportAPI)
}
fullURL := makeURL(conn, exportAPI, params)
if !quiet {
log.Printf("Calling HTTP GET %v\n", fullURL)
Expand Down Expand Up @@ -138,6 +142,7 @@ var quiet = false

func main() {
kibanaURL := flag.String("kibana", "http://localhost:5601", "Kibana URL")
spaceID := flag.String("space-id", "", "Space ID")
dashboard := flag.String("dashboard", "", "Dashboard ID")
fileOutput := flag.String("output", "output.json", "Output file")
ymlFile := flag.String("yml", "", "Path to the module.yml file containing the dashboards")
Expand Down Expand Up @@ -171,7 +176,7 @@ func main() {
if err != nil {
log.Fatalf("fail to create directory %s: %v", directory, err)
}
err = Export(client, *kibanaURL, dashboard["id"], filepath.Join(directory, dashboard["file"]))
err = Export(client, *kibanaURL, *spaceID, dashboard["id"], filepath.Join(directory, dashboard["file"]))
if err != nil {
log.Fatalf("fail to export the dashboards: %s", err)
}
Expand All @@ -180,7 +185,7 @@ func main() {
}

if len(*dashboard) > 0 {
err := Export(client, *kibanaURL, *dashboard, *fileOutput)
err := Export(client, *kibanaURL, *spaceID, *dashboard, *fileOutput)
if err != nil {
log.Fatalf("fail to export the dashboards: %s", err)
}
Expand Down
9 changes: 9 additions & 0 deletions docs/devguide/newdashboards.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,15 @@ go run dev-tools/cmd/dashboards/export_dashboards.go -yml filebeat/module/system
-------------------


===== Export dashboards from a Kibana Space

If you are using the Kibana Spaces feature and want to export dashboards from a specific Space, pass the Space ID to the `export_dashboards.go` script:

[source,shell]
-------------------
go run dev-tools/cmd/dashboards/export_dashboards.go -space-id my-space [other-options]
-------------------


==== Exporting Kibana 5.x dashboards

Expand Down
5 changes: 5 additions & 0 deletions filebeat/filebeat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ setup.kibana:
# IPv6 addresses should always be defined as: https://[2001:db8::1]:5601
#host: "localhost:5601"

# Kibana Space ID
# ID of the Kibana Space into which the dashboards should be loaded. By default,
# the Default Space will be used.
#space.id:

#============================= Elastic Cloud ==================================

# These settings simplify using filebeat with the Elastic Cloud (https://cloud.elastic.co/).
Expand Down
5 changes: 5 additions & 0 deletions heartbeat/heartbeat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ setup.kibana:
# IPv6 addresses should always be defined as: https://[2001:db8::1]:5601
#host: "localhost:5601"

# Kibana Space ID
# ID of the Kibana Space into which the dashboards should be loaded. By default,
# the Default Space will be used.
#space.id:

#============================= Elastic Cloud ==================================

# These settings simplify using heartbeat with the Elastic Cloud (https://cloud.elastic.co/).
Expand Down
5 changes: 5 additions & 0 deletions libbeat/_meta/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ setup.kibana:
# IPv6 addresses should always be defined as: https://[2001:db8::1]:5601
#host: "localhost:5601"

# Kibana Space ID
# ID of the Kibana Space into which the dashboards should be loaded. By default,
# the Default Space will be used.
#space.id:

#============================= Elastic Cloud ==================================

# These settings simplify using beatname with the Elastic Cloud (https://cloud.elastic.co/).
Expand Down
7 changes: 6 additions & 1 deletion libbeat/kibana/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"io/ioutil"
"net/http"
"net/url"
"path"
"strings"

"github.com/pkg/errors"
Expand Down Expand Up @@ -88,7 +89,11 @@ func NewKibanaClient(cfg *common.Config) (*Client, error) {

// NewClientWithConfig creates and returns a kibana client using the given config
func NewClientWithConfig(config *ClientConfig) (*Client, error) {
kibanaURL, err := common.MakeURL(config.Protocol, config.Path, config.Host, 5601)
p := config.Path
if config.SpaceID != "" {
p = path.Join(p, "s", config.SpaceID)
}
kibanaURL, err := common.MakeURL(config.Protocol, p, config.Host, 5601)
if err != nil {
return nil, fmt.Errorf("invalid Kibana host: %v", err)
}
Expand Down
2 changes: 2 additions & 0 deletions libbeat/kibana/client_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type ClientConfig struct {
Protocol string `config:"protocol"`
Host string `config:"host"`
Path string `config:"path"`
SpaceID string `config:"space.id"`
Username string `config:"username"`
Password string `config:"password"`
TLS *tlscommon.Config `config:"ssl"`
Expand All @@ -39,6 +40,7 @@ var (
Protocol: "http",
Host: "localhost:5601",
Path: "",
SpaceID: "",
Username: "",
Password: "",
Timeout: 90 * time.Second,
Expand Down
1 change: 1 addition & 0 deletions libbeat/tests/system/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ urllib3==1.22
websocket-client==0.47.0
parameterized==0.6.1
jsondiff==1.1.2
semver==2.8.1
92 changes: 91 additions & 1 deletion libbeat/tests/system/test_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import subprocess
from nose.plugins.attrib import attr
import unittest

import requests
import semver

INTEGRATION_TESTS = os.environ.get('INTEGRATION_TESTS', False)

Expand Down Expand Up @@ -36,6 +37,40 @@ def test_load_dashboard(self):

assert self.log_contains("Kibana dashboards successfully loaded") is True

@unittest.skipUnless(INTEGRATION_TESTS, "integration test")
@attr('integration')
def test_load_dashboard_into_space(self, create_space=True):
"""
Test loading dashboards into Kibana space
"""
version = self.get_version()
if semver.compare(version, "6.5.0") == -1:
# Skip for Kibana versions < 6.5.0 as Kibana Spaces not available
raise SkipTest

self.render_config_template()
if create_space:
self.create_kibana_space()

beat = self.start_beat(
logging_args=["-e", "-d", "*"],
extra_args=["setup",
"--dashboards",
"-E", "setup.dashboards.file=" +
os.path.join(self.beat_path, "tests", "files", "testbeat-dashboards.zip"),
"-E", "setup.dashboards.beat=testbeat",
"-E", "setup.kibana.protocol=http",
"-E", "setup.kibana.host=" + self.get_kibana_host(),
"-E", "setup.kibana.port=" + self.get_kibana_port(),
"-E", "setup.kibana.space.id=foo-bar",
"-E", "output.elasticsearch.hosts=['" + self.get_host() + "']",
"-E", "output.file.enabled=false"]
)

beat.check_wait(exit_code=0)

assert self.log_contains("Kibana dashboards successfully loaded") is True

@unittest.skipUnless(INTEGRATION_TESTS, "integration test")
@attr('integration')
def test_load_only_index_patterns(self):
Expand Down Expand Up @@ -88,6 +123,36 @@ def test_export_dashboard(self):

os.remove("output.json")

@unittest.skipUnless(INTEGRATION_TESTS, "integration test")
@attr('integration')
def test_export_dashboard_from_space(self):
"""
Test export dashboards from Kibana space and remove unsupported characters
"""
version = self.get_version()
if semver.compare(version, "6.5.0") == -1:
# Skip for Kibana versions < 6.5.0 as Kibana Spaces not available
raise SkipTest

self.test_load_dashboard_into_space(False)

path = os.path.normpath(self.beat_path + "/../dev-tools/cmd/dashboards/export_dashboards.go")
command = path + " -kibana http://" + self.get_kibana_host() + ":" + self.get_kibana_port()
command = "go run " + command + " -dashboard Metricbeat-system-overview -space-id foo-bar"

p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
content, err = p.communicate()

assert p.returncode == 0

assert os.path.isfile("output.json") is True

with open('output.json') as f:
content = f.read()
assert "Metricbeat-system-overview" in content

os.remove("output.json")

def get_host(self):
return os.getenv('ES_HOST', 'localhost') + ':' + os.getenv('ES_PORT', '9200')

Expand All @@ -96,3 +161,28 @@ def get_kibana_host(self):

def get_kibana_port(self):
return os.getenv('KIBANA_PORT', '5601')

def create_kibana_space(self):
url = "http://" + self.get_kibana_host() + ":" + self.get_kibana_port() + \
"/api/spaces/space"
data = {
"id": "foo-bar",
"name": "Foo bar space"
}

headers = {
"kbn-xsrf": "1"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity: Why is this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

r = requests.post(url, json=data, headers=headers)
assert r.status_code == 200

def get_version(self):
url = "http://" + self.get_kibana_host() + ":" + self.get_kibana_port() + \
"/api/status"

r = requests.get(url)
body = r.json()
version = body["version"]["number"]

return version
5 changes: 5 additions & 0 deletions metricbeat/metricbeat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ setup.kibana:
# IPv6 addresses should always be defined as: https://[2001:db8::1]:5601
#host: "localhost:5601"

# Kibana Space ID
# ID of the Kibana Space into which the dashboards should be loaded. By default,
# the Default Space will be used.
#space.id:

#============================= Elastic Cloud ==================================

# These settings simplify using metricbeat with the Elastic Cloud (https://cloud.elastic.co/).
Expand Down
5 changes: 5 additions & 0 deletions packetbeat/packetbeat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ setup.kibana:
# IPv6 addresses should always be defined as: https://[2001:db8::1]:5601
#host: "localhost:5601"

# Kibana Space ID
# ID of the Kibana Space into which the dashboards should be loaded. By default,
# the Default Space will be used.
#space.id:

#============================= Elastic Cloud ==================================

# These settings simplify using packetbeat with the Elastic Cloud (https://cloud.elastic.co/).
Expand Down
5 changes: 5 additions & 0 deletions winlogbeat/winlogbeat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ setup.kibana:
# IPv6 addresses should always be defined as: https://[2001:db8::1]:5601
#host: "localhost:5601"

# Kibana Space ID
# ID of the Kibana Space into which the dashboards should be loaded. By default,
# the Default Space will be used.
#space.id:

#============================= Elastic Cloud ==================================

# These settings simplify using winlogbeat with the Elastic Cloud (https://cloud.elastic.co/).
Expand Down