From 5723fe86c7f857915a408004045291c108dbb398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Wed, 14 Nov 2018 17:14:07 +0100 Subject: [PATCH 1/3] minor refacotring of module generator --- filebeat/scripts/generator/module/main.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/filebeat/scripts/generator/module/main.go b/filebeat/scripts/generator/module/main.go index dedf1f3e279..069ce79efd1 100644 --- a/filebeat/scripts/generator/module/main.go +++ b/filebeat/scripts/generator/module/main.go @@ -39,7 +39,12 @@ func generateModule(module, modulesPath, beatsPath string) error { replace := map[string]string{"module": module} templatesPath := path.Join(beatsPath, "scripts", "module") - filesToCopy := []string{path.Join("_meta", "fields.yml"), path.Join("_meta", "docs.asciidoc"), path.Join("_meta", "config.yml"), path.Join("module.yml")} + filesToCopy := []string{ + path.Join("_meta", "fields.yml"), + path.Join("_meta", "docs.asciidoc"), + path.Join("_meta", "config.yml"), + "module.yml", + } generator.CopyTemplates(templatesPath, modulePath, filesToCopy, replace) if err != nil { return err From 5112e1f2958866491c1a86150e5d8dd79070f0f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Wed, 14 Nov 2018 17:15:33 +0100 Subject: [PATCH 2/3] generator.CreateDirectories accepts vararg --- filebeat/scripts/generator/fileset/main.go | 2 +- filebeat/scripts/generator/generator.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/filebeat/scripts/generator/fileset/main.go b/filebeat/scripts/generator/fileset/main.go index 94d0ac6b6a2..3879d238e8f 100644 --- a/filebeat/scripts/generator/fileset/main.go +++ b/filebeat/scripts/generator/fileset/main.go @@ -32,7 +32,7 @@ func generateFileset(module, fileset, modulesPath, beatsPath string) error { return fmt.Errorf("fileset already exists: %s", fileset) } - err := generator.CreateDirectories(filesetPath, []string{"", "_meta", "test", "config", "ingest"}) + err := generator.CreateDirectories(filesetPath, "", "_meta", "test", "config", "ingest") if err != nil { return err } diff --git a/filebeat/scripts/generator/generator.go b/filebeat/scripts/generator/generator.go index e5aaf771ab4..40df8311ede 100644 --- a/filebeat/scripts/generator/generator.go +++ b/filebeat/scripts/generator/generator.go @@ -35,7 +35,7 @@ func DirExists(dir string) bool { } // CreateDirectories create directories in baseDir -func CreateDirectories(baseDir string, directories []string) error { +func CreateDirectories(baseDir string, directories ...string) error { for _, d := range directories { p := path.Join(baseDir, d) err := os.MkdirAll(p, 0750) From 754bd40de83cacd9dc34b6ce0aaeae2f68eafed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Wed, 14 Nov 2018 17:16:48 +0100 Subject: [PATCH 3/3] export dashboard creates folders and saves dashboards in case of modules --- filebeat/scripts/generator/dashboards.go | 89 +++++++++++++++++++++++ filebeat/scripts/generator/module/main.go | 7 +- libbeat/cmd/export/dashboard.go | 15 ++++ 3 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 filebeat/scripts/generator/dashboards.go diff --git a/filebeat/scripts/generator/dashboards.go b/filebeat/scripts/generator/dashboards.go new file mode 100644 index 00000000000..f69f7013db1 --- /dev/null +++ b/filebeat/scripts/generator/dashboards.go @@ -0,0 +1,89 @@ +// 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 generator + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/paths" +) + +const ( + dashboardEntry = `- id: %s + file: %s +` +) + +func AddModuleDashboard(beatName, module, kibanaVersion, dashboardID string, dashboard common.MapStr, suffix string) error { + version, err := common.NewVersion(kibanaVersion) + if err != nil { + return err + } + if version.Major < 6 { + return fmt.Errorf("saving exported dashboards is not available for Kibana version '%s'", version.String()) + } + + modulePath := filepath.Join(paths.Resolve(paths.Home, "module"), module) + stat, err := os.Stat(modulePath) + if err != nil || !stat.IsDir() { + return fmt.Errorf("no such module: %s\n", modulePath) + } + + dashboardFile := strings.Title(beatName) + "-" + module + "-" + suffix + ".json" + + err = saveDashboardToFile(version, dashboard, dashboardFile, modulePath) + if err != nil { + return fmt.Errorf("cannot save dashboard to file: %+v", err) + } + + return addDashboardToModuleYML(dashboardID, dashboardFile, modulePath) +} + +func saveDashboardToFile(version *common.Version, dashboard common.MapStr, dashboardFile, modulePath string) error { + dashboardsPath := "_meta/kibana/" + strconv.Itoa(version.Major) + "/dashboard" + err := CreateDirectories(modulePath, dashboardsPath) + if err != nil { + return err + } + + dashboardPath := filepath.Join(modulePath, dashboardsPath, dashboardFile) + bytes, err := json.Marshal(dashboard) + if err != nil { + return err + } + + return ioutil.WriteFile(dashboardPath, bytes, 0644) +} + +func addDashboardToModuleYML(dashboardID, dashboardFile, modulePath string) error { + content := fmt.Sprintf(dashboardEntry, dashboardID, dashboardFile) + + f, err := os.OpenFile(filepath.Join(modulePath, "module.yml"), os.O_WRONLY|os.O_APPEND, 0644) + if err == nil { + _, err = f.Write([]byte(content)) + } + + return err +} diff --git a/filebeat/scripts/generator/module/main.go b/filebeat/scripts/generator/module/main.go index 069ce79efd1..6128d014039 100644 --- a/filebeat/scripts/generator/module/main.go +++ b/filebeat/scripts/generator/module/main.go @@ -32,11 +32,6 @@ func generateModule(module, modulesPath, beatsPath string) error { return fmt.Errorf("module already exists: %s", module) } - err := generator.CreateDirectories(modulePath, []string{path.Join("_meta", "kibana", "6")}) - if err != nil { - return err - } - replace := map[string]string{"module": module} templatesPath := path.Join(beatsPath, "scripts", "module") filesToCopy := []string{ @@ -45,7 +40,7 @@ func generateModule(module, modulesPath, beatsPath string) error { path.Join("_meta", "config.yml"), "module.yml", } - generator.CopyTemplates(templatesPath, modulePath, filesToCopy, replace) + err := generator.CopyTemplates(templatesPath, modulePath, filesToCopy, replace) if err != nil { return err } diff --git a/libbeat/cmd/export/dashboard.go b/libbeat/cmd/export/dashboard.go index 59a6fa04cc3..7a93df78f7a 100644 --- a/libbeat/cmd/export/dashboard.go +++ b/libbeat/cmd/export/dashboard.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/cobra" + "github.com/elastic/beats/filebeat/scripts/generator" "github.com/elastic/beats/libbeat/cmd/instance" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/kibana" @@ -35,6 +36,8 @@ func GenDashboardCmd(name, idxPrefix, beatVersion string) *cobra.Command { Short: "Export defined dashboard to stdout", Run: func(cmd *cobra.Command, args []string) { dashboard, _ := cmd.Flags().GetString("id") + module, _ := cmd.Flags().GetString("module") + suffix, _ := cmd.Flags().GetString("suffix") b, err := instance.NewBeat(name, idxPrefix, beatVersion) if err != nil { @@ -63,11 +66,23 @@ func GenDashboardCmd(name, idxPrefix, beatVersion string) *cobra.Command { fmt.Fprintf(os.Stderr, "Error getting dashboard: %+v\n", err) os.Exit(1) } + + if module != "" { + err := generator.AddModuleDashboard(name, module, client.GetVersion(), dashboard, result, suffix) + if err != nil { + fmt.Fprintf(os.Stderr, "Error adding dashboard to module '%s': %+v\n", module, err) + os.Exit(2) + } + return + } + fmt.Println(result.StringToPrint()) }, } genTemplateConfigCmd.Flags().String("id", "", "Dashboard id") + genTemplateConfigCmd.Flags().String("module", "", "Name of the module to save for") + genTemplateConfigCmd.Flags().String("suffix", "overview", "Suffix of the dashboard name") return genTemplateConfigCmd }