-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Dashboard exporting saves to file in case of modules #9076
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. exported function AddModuleDashboard should have comment or be unexported |
||
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()) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good to report that you need at least kibana 6. |
||
|
||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. error strings should not be capitalized or end with punctuation or a newline |
||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you want to report a more accurate error, I think you actually want to use https://golang.org/pkg/os/#IsExist instead of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? If there is no error it means the file exists and I have the proper permission to access it. I also need to check if that module is a folder. If it is not a folder, I cannot create more folders under it and cannot saves files. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I followed the same check as it is done in case of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fair enough |
||
|
||
dashboardFile := strings.Title(beatName) + "-" + module + "-" + suffix + ".json" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why 'title'? Given default case insensitivity Windows/macOS filesystems can be a pain with in comparison to Linux. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought this format is the name convention for Filebeat module dashboards, as 99% percent of them are named Filebeat-{modulename}-{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)) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. better use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh... it's an append. In this case check the amount of bytes written. If some bytes are written, but write is incomplete then the file is broken. |
||
|
||
return err | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the module.yml this looks like generic YAML files, minus the extra space between lines. Is there a specific reason why we don't use the YAML package and structs to serialize / unserialize content.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, nothing. I planned to use the yaml package to read and write module.yml. I was just curious if you like the direction of the PR. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kvch I like it :)