From 245b3e1b2ff12449007d6aa01dceee050d40ffa5 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Mon, 4 Jun 2018 18:14:08 +0200 Subject: [PATCH] Update export_dashboard script to export full dashboard json doc (#7241) In https://github.com/elastic/beats/pull/7239 support to export a dashboard is a added to each Beat. This is expected to be used by users. The export_dashboard script from the Beats repository is expected by the Devs and contributors which want to add new dashboards. In https://github.com/elastic/beats/pull/7224 the dashboards are modified to be stored with decoded json objects for better versioning. This change modifies the export dashboard script so it generates the same decoded output so no additional conversion is needed. --- dev-tools/cmd/dashboards/export_dashboards.go | 61 ++++++++----------- libbeat/kibana/dashboard.go | 8 +-- 2 files changed, 30 insertions(+), 39 deletions(-) diff --git a/dev-tools/cmd/dashboards/export_dashboards.go b/dev-tools/cmd/dashboards/export_dashboards.go index 4dfe8709f183..7d8121fc77d3 100644 --- a/dev-tools/cmd/dashboards/export_dashboards.go +++ b/dev-tools/cmd/dashboards/export_dashboards.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/kibana" ) var exportAPI = "/api/kibana/dashboards/export" @@ -29,39 +30,6 @@ func makeURL(url, path string, params url.Values) string { return strings.Join([]string{url, path, "?", params.Encode()}, "") } -func ExtractIndexPattern(body []byte) ([]byte, error) { - var contents common.MapStr - - err := json.Unmarshal(body, &contents) - if err != nil { - return nil, err - } - - objects, ok := contents["objects"].([]interface{}) - if !ok { - return nil, fmt.Errorf("Key objects not found or wrong type") - } - - var result []interface{} - for _, obj := range objects { - _type, ok := obj.(map[string]interface{})["type"].(string) - if !ok { - return nil, fmt.Errorf("type key not found or not string") - } - if _type != "index-pattern" || indexPattern { - result = append(result, obj) - } - } - contents["objects"] = result - - newBody, err := json.MarshalIndent(contents, "", " ") - if err != nil { - return nil, fmt.Errorf("Error mashaling: %v", err) - } - - return newBody, nil -} - func Export(client *http.Client, conn string, dashboard string, out string) error { params := url.Values{} @@ -90,19 +58,42 @@ func Export(client *http.Client, conn string, dashboard string, out string) erro return fmt.Errorf("HTTP GET %s fails with %s, %s", fullURL, resp.Status, body) } - body, err = ExtractIndexPattern(body) + data, err := kibana.RemoveIndexPattern(body) if err != nil { return fmt.Errorf("fail to extract the index pattern: %v", err) } - err = ioutil.WriteFile(out, body, 0666) + objects := data["objects"].([]interface{}) + for _, obj := range objects { + o := obj.(common.MapStr) + + decodeValue(o, "attributes.uiStateJSON") + decodeValue(o, "attributes.visState") + decodeValue(o, "attributes.optionsJSON") + decodeValue(o, "attributes.panelsJSON") + decodeValue(o, "attributes.kibanaSavedObjectMeta.searchSourceJSON") + } + data["objects"] = objects + err = ioutil.WriteFile(out, []byte(data.StringToPrint()), 0666) if !quiet { fmt.Printf("The dashboard %s was exported under the %s file\n", dashboard, out) } return err } +func decodeValue(data common.MapStr, key string) { + v, err := data.GetValue(key) + if err != nil { + return + } + s := v.(string) + var d common.MapStr + json.Unmarshal([]byte(s), &d) + + data.Put(key, d) +} + func ReadManifest(file string) ([]map[string]string, error) { cfg, err := common.LoadFile(file) if err != nil { diff --git a/libbeat/kibana/dashboard.go b/libbeat/kibana/dashboard.go index bb996b362d22..47ba251a72ab 100644 --- a/libbeat/kibana/dashboard.go +++ b/libbeat/kibana/dashboard.go @@ -13,7 +13,7 @@ func RemoveIndexPattern(data []byte) (common.MapStr, error) { var kbResult struct { // Has to be defined as interface instead of Type directly as it has to be assigned again // and otherwise would not contain the full content. - Objects []interface{} + Objects []common.MapStr } var result common.MapStr @@ -32,11 +32,11 @@ func RemoveIndexPattern(data []byte) (common.MapStr, error) { var objs []interface{} for _, obj := range kbResult.Objects { - t, ok := obj.(map[string]interface{})["type"].(string) - if !ok { + v, err := obj.GetValue("type") + if err != nil { return nil, fmt.Errorf("type key not found or not string") } - if t != "index-pattern" { + if v != "index-pattern" { objs = append(objs, obj) } }