Skip to content

Commit

Permalink
Replace index patterns in TSVB visualizations
Browse files Browse the repository at this point in the history
When customizing the index pattern with `setup.dashboards.index`,
references to index patterns need to be replaced in imported dashboards.
It was not being done with objects that contain the index pattern in
the `visState` object, as is the case of TSVB visualizations.
  • Loading branch information
jsoriano committed Aug 9, 2018
1 parent 9621b23 commit b0fc21a
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 30 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.asciidoc
Expand Up @@ -37,7 +37,8 @@ https://github.com/elastic/beats/compare/v6.4.0...master[Check the HEAD diff]
- Fix potential data loss on OS X in spool file by using fcntl with F_FULLFSYNC. {pull}7859[7859]
- Improve fsync on linux, by assuming the kernel resets error flags of failed writes. {pull}7859[7859]
- Remove unix-like permission checks on Windows, so files can be opened. {issue}7849[7849]
- Deregister pipeline loader callback when inputsRunner is stopped. {pull}[7893][7893]
- Deregister pipeline loader callback when inputsRunner is stopped. {pull}7893[7893]
- Replace index patterns in TSVB visualizations. {pull}7929[7929]

*Auditbeat*

Expand Down
5 changes: 4 additions & 1 deletion libbeat/dashboards/es_loader.go
Expand Up @@ -217,9 +217,12 @@ func (loader ElasticsearchLoader) importVisualization(file string) error {

if loader.config.Index != "" {
if savedObject, ok := vizContent["kibanaSavedObjectMeta"].(map[string]interface{}); ok {

vizContent["kibanaSavedObjectMeta"] = ReplaceIndexInSavedObject(loader.config.Index, savedObject)
}

if visState, ok := vizContent["visState"].(string); ok {
vizContent["visState"] = ReplaceIndexInVisState(loader.config.Index, visState)
}
}

vizName := strings.TrimSuffix(filepath.Base(file), filepath.Ext(file))
Expand Down
104 changes: 76 additions & 28 deletions libbeat/dashboards/modify_json.go
Expand Up @@ -42,24 +42,29 @@ type JSONFormat struct {
}

func ReplaceIndexInIndexPattern(index string, content common.MapStr) common.MapStr {
if index == "" {
return content
}

objects, ok := content["objects"].([]interface{})
if !ok {
return content
}

// change index pattern name
for i, object := range objects {
objectMap, ok := object.(map[string]interface{})
if !ok {
continue
}

if index != "" {
// change index pattern name
if objects, ok := content["objects"].([]interface{}); ok {
for i, object := range objects {
if objectMap, ok := object.(map[string]interface{}); ok {
objectMap["id"] = index

if attributes, ok := objectMap["attributes"].(map[string]interface{}); ok {
attributes["title"] = index
objectMap["attributes"] = attributes
}
objects[i] = objectMap
}
}
content["objects"] = objects
objectMap["id"] = index
if attributes, ok := objectMap["attributes"].(map[string]interface{}); ok {
attributes["title"] = index
}
objects[i] = objectMap
}
content["objects"] = objects

return content
}
Expand Down Expand Up @@ -97,28 +102,71 @@ func ReplaceIndexInSavedObject(index string, kibanaSavedObject map[string]interf
return kibanaSavedObject
}

func ReplaceIndexInDashboardObject(index string, content common.MapStr) common.MapStr {
// ReplaceIndexInVisState replaces index appearing in visState params objects
func ReplaceIndexInVisState(index string, visStateJSON string) string {

var visState map[string]interface{}
err := json.Unmarshal([]byte(visStateJSON), &visState)
if err != nil {
logp.Err("Fail to unmarshal visState: %v", err)
return visStateJSON
}

params, ok := visState["params"].(map[string]interface{})
if !ok {
return visStateJSON
}

// Don't set it if it was not set before
if pattern, ok := params["index_pattern"].(string); !ok || len(pattern) == 0 {
return visStateJSON
}

params["index_pattern"] = index

d, err := json.Marshal(visState)
if err != nil {
logp.Err("Fail to marshal visState: %v", err)
return visStateJSON
}

return string(d)
}

// ReplaceIndexInDashboardObject replaces references to the index pattern in dashboard objects
func ReplaceIndexInDashboardObject(index string, content common.MapStr) common.MapStr {
if index == "" {
return content
}
if objects, ok := content["objects"].([]interface{}); ok {
for i, object := range objects {
if objectMap, ok := object.(map[string]interface{}); ok {
if attributes, ok := objectMap["attributes"].(map[string]interface{}); ok {

if kibanaSavedObject, ok := attributes["kibanaSavedObjectMeta"].(map[string]interface{}); ok {
objects, ok := content["objects"].([]interface{})
if !ok {
return content
}

for i, object := range objects {
objectMap, ok := object.(map[string]interface{})
if !ok {
continue
}

attributes, ok := objectMap["attributes"].(map[string]interface{})
if !ok {
continue
}

attributes["kibanaSavedObjectMeta"] = ReplaceIndexInSavedObject(index, kibanaSavedObject)
}
if kibanaSavedObject, ok := attributes["kibanaSavedObjectMeta"].(map[string]interface{}); ok {
attributes["kibanaSavedObjectMeta"] = ReplaceIndexInSavedObject(index, kibanaSavedObject)
}

objectMap["attributes"] = attributes
}
objects[i] = objectMap
}
if visState, ok := attributes["visState"].(string); ok {
attributes["visState"] = ReplaceIndexInVisState(index, visState)
}
content["objects"] = objects

objects[i] = objectMap
}
content["objects"] = objects

return content
}

Expand Down
42 changes: 42 additions & 0 deletions libbeat/dashboards/modify_json_test.go
Expand Up @@ -69,3 +69,45 @@ func TestReplaceStringInDashboard(t *testing.T) {
assert.Equal(t, test.expected, result)
}
}

func TestReplaceIndexInDashboardObject(t *testing.T) {
tests := []struct {
dashboard common.MapStr
pattern string
expected common.MapStr
}{
{
common.MapStr{"objects": []interface{}{map[string]interface{}{
"attributes": map[string]interface{}{
"kibanaSavedObjectMeta": map[string]interface{}{
"searchSourceJSON": "{\"index\":\"metricbeat-*\"}",
},
}}}},
"otherindex-*",
common.MapStr{"objects": []interface{}{map[string]interface{}{
"attributes": map[string]interface{}{
"kibanaSavedObjectMeta": map[string]interface{}{
"searchSourceJSON": "{\"index\":\"otherindex-*\"}",
},
}}}},
},
{
common.MapStr{"objects": []interface{}{map[string]interface{}{
"attributes": map[string]interface{}{
"kibanaSavedObjectMeta": map[string]interface{}{},
"visState": "{\"params\":{\"index_pattern\":\"metricbeat-*\"}}",
}}}},
"otherindex-*",
common.MapStr{"objects": []interface{}{map[string]interface{}{
"attributes": map[string]interface{}{
"kibanaSavedObjectMeta": map[string]interface{}{},
"visState": "{\"params\":{\"index_pattern\":\"otherindex-*\"}}",
}}}},
},
}

for _, test := range tests {
result := ReplaceIndexInDashboardObject(test.pattern, test.dashboard)
assert.Equal(t, test.expected, result)
}
}

0 comments on commit b0fc21a

Please sign in to comment.