forked from elastic/beats
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Simple conversion of the format returned by the API (elastic#10019)
* Simple conversion conversion of the format returned by the API The Kibana API for CM is undergoing internal changes to better allow future scalability of the configurations, one of the requirements for this move was to flatten as much as possible the configuration file so the format would be the same independant of the key that need to received ot the configuration. It will be up to the manager to take the JSON format and convert it into something that our Configuration can understand. ref: elastic/kibana#27717
- Loading branch information
Showing
6 changed files
with
290 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
// or more contributor license agreements. Licensed under the Elastic License; | ||
// you may not use this file except in compliance with the Elastic License. | ||
|
||
package api | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
type converter func(map[string]interface{}) (map[string]interface{}, error) | ||
|
||
var mapper = map[string]converter{ | ||
".inputs": noopConvert, | ||
".modules": convertMultiple, | ||
"output": convertSingle, | ||
} | ||
|
||
var errSubTypeNotFound = fmt.Errorf("'%s' key not found", subTypeKey) | ||
|
||
var ( | ||
subTypeKey = "_sub_type" | ||
moduleKey = "module" | ||
) | ||
|
||
func selectConverter(t string) converter { | ||
for k, v := range mapper { | ||
if strings.Index(t, k) > -1 { | ||
return v | ||
} | ||
} | ||
return noopConvert | ||
} | ||
|
||
func convertSingle(m map[string]interface{}) (map[string]interface{}, error) { | ||
subType, err := extractSubType(m) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
delete(m, subTypeKey) | ||
newMap := map[string]interface{}{subType: m} | ||
return newMap, nil | ||
} | ||
|
||
func convertMultiple(m map[string]interface{}) (map[string]interface{}, error) { | ||
subType, err := extractSubType(m) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
v, ok := m[moduleKey] | ||
|
||
if ok && v != subType { | ||
return nil, fmt.Errorf("module key already exist in the raw document and doesn't match the 'sub_type', expecting '%s' and received '%s", subType, v) | ||
} | ||
|
||
m[moduleKey] = subType | ||
delete(m, subTypeKey) | ||
return m, nil | ||
} | ||
|
||
func noopConvert(m map[string]interface{}) (map[string]interface{}, error) { | ||
return m, nil | ||
} | ||
|
||
func extractSubType(m map[string]interface{}) (string, error) { | ||
subType, ok := m[subTypeKey] | ||
if !ok { | ||
return "", errSubTypeNotFound | ||
} | ||
|
||
k, ok := subType.(string) | ||
if !ok { | ||
return "", fmt.Errorf("invalid type for `sub_type`, expecting a string received %T", subType) | ||
} | ||
return k, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
// or more contributor license agreements. Licensed under the Elastic License; | ||
// you may not use this file except in compliance with the Elastic License. | ||
|
||
package api | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestConvertAPI(t *testing.T) { | ||
tests := map[string]struct { | ||
t string | ||
config map[string]interface{} | ||
expected map[string]interface{} | ||
err bool | ||
}{ | ||
"output": { | ||
t: "output", | ||
config: map[string]interface{}{ | ||
"_sub_type": "elasticsearch", | ||
"username": "foobar", | ||
}, | ||
expected: map[string]interface{}{ | ||
"elasticsearch": map[string]interface{}{ | ||
"username": "foobar", | ||
}, | ||
}, | ||
}, | ||
"filebeat inputs": { | ||
t: "filebeat.inputs", | ||
config: map[string]interface{}{ | ||
"type": "log", | ||
"paths": []string{ | ||
"/var/log/message.log", | ||
"/var/log/system.log", | ||
}, | ||
}, | ||
expected: map[string]interface{}{ | ||
"type": "log", | ||
"paths": []string{ | ||
"/var/log/message.log", | ||
"/var/log/system.log", | ||
}, | ||
}, | ||
}, | ||
"filebeat modules": { | ||
t: "filebeat.modules", | ||
config: map[string]interface{}{ | ||
"_sub_type": "system", | ||
}, | ||
expected: map[string]interface{}{ | ||
"module": "system", | ||
}, | ||
}, | ||
"metricbeat modules": { | ||
t: "metricbeat.modules", | ||
config: map[string]interface{}{ | ||
"_sub_type": "logstash", | ||
}, | ||
expected: map[string]interface{}{ | ||
"module": "logstash", | ||
}, | ||
}, | ||
"badly formed output": { | ||
err: true, | ||
t: "output", | ||
config: map[string]interface{}{ | ||
"nosubtype": "logstash", | ||
}, | ||
}, | ||
"badly formed filebeat module": { | ||
err: true, | ||
t: "filebeat.modules", | ||
config: map[string]interface{}{ | ||
"nosubtype": "logstash", | ||
}, | ||
}, | ||
"badly formed metricbeat module": { | ||
err: true, | ||
t: "metricbeat.modules", | ||
config: map[string]interface{}{ | ||
"nosubtype": "logstash", | ||
}, | ||
}, | ||
"unknown type is passthrough": { | ||
t: "unkown", | ||
config: map[string]interface{}{ | ||
"nosubtype": "logstash", | ||
}, | ||
expected: map[string]interface{}{ | ||
"nosubtype": "logstash", | ||
}, | ||
}, | ||
} | ||
|
||
for name, test := range tests { | ||
test := test | ||
t.Run(name, func(t *testing.T) { | ||
converter := selectConverter(test.t) | ||
newMap, err := converter(test.config) | ||
if !assert.Equal(t, test.err, err != nil) { | ||
return | ||
} | ||
assert.True(t, reflect.DeepEqual(newMap, test.expected)) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
// or more contributor license agreements. Licensed under the Elastic License; | ||
// you may not use this file except in compliance with the Elastic License. | ||
|
||
/* | ||
The Kibana CM Api returns a configuration format which cannot be ingested directly by our | ||
configuration parser, it need to be transformed from the generic format into an adapted format | ||
which is dependant on the type of configuration. | ||
Translations: | ||
Type: output | ||
{ | ||
"configuration_blocks": [ | ||
{ | ||
"config": { | ||
"_sub_type": "elasticsearch" | ||
"_id": "12312341231231" | ||
"hosts": [ "localhost" ], | ||
"password": "foobar" | ||
"username": "elastic" | ||
}, | ||
"type": "output" | ||
} | ||
] | ||
} | ||
YAML representation: | ||
{ | ||
"elasticsearch": { | ||
"hosts": [ "localhost" ], | ||
"password": "foobar" | ||
"username": "elastic" | ||
} | ||
} | ||
Type: *.modules | ||
{ | ||
"configuration_blocks": [ | ||
{ | ||
"config": { | ||
"_sub_type": "system" | ||
"_id": "12312341231231" | ||
"path" "foobar" | ||
}, | ||
"type": "filebeat.module" | ||
} | ||
] | ||
} | ||
YAML representation: | ||
[ | ||
{ | ||
"module": "system" | ||
"path": "foobar" | ||
} | ||
] | ||
*/ | ||
|
||
package api |