Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions internal/fields/testdata/fields/fields.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
fields:
- name: code
type: keyword
- name: pid
type: keyword
- name: ppid
type: keyword
- name: flattened
type: group
fields:
Expand Down Expand Up @@ -78,3 +82,7 @@
multi_fields:
- name: text
type: text
- name: tags
type: keyword
normalize:
- array
7 changes: 5 additions & 2 deletions internal/fields/testdata/numeric.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
{
"foo": {
"code": 42,
"pid": [345, 678, 901],
"ppid": [],
"flattened": {
"request_parameters": {
"userName": "Bob",
"groupName": "admin"
}
}
}
}
},
"tags": []
}
22 changes: 19 additions & 3 deletions internal/fields/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ func (v *Validator) validateScalarElement(key string, val interface{}, doc commo
// Convert numeric keyword fields to string for validation.
_, found := v.numericKeywordFields[key]
if (found || v.defaultNumericConversion) && isNumericKeyword(*definition, val) {
val = fmt.Sprintf("%q", val)
val = convertNumericKeyword(val)
}

if !v.disabledNormalization {
Expand Down Expand Up @@ -692,12 +692,15 @@ func createDocExpandingObjects(doc common.MapStr) (common.MapStr, error) {
}
return newDoc, nil
}
func isNumericKeyword(definition FieldDefinition, val interface{}) bool {

// isNumericKeyword is used to identify values that can be numbers in the documents, but are ingested
// as keywords.
func isNumericKeyword(definition FieldDefinition, val any) bool {
var isNumber bool
switch val := val.(type) {
case bool, []bool, float64, []float64:
isNumber = true
case []interface{}:
case []any:
isNumber = true
loop:
for _, v := range val {
Expand All @@ -712,6 +715,19 @@ func isNumericKeyword(definition FieldDefinition, val interface{}) bool {
return isNumber && (definition.Type == "keyword" || definition.Type == "constant_keyword")
}

func convertNumericKeyword(val any) any {
switch val := val.(type) {
case []any:
converted := make([]any, len(val))
for i, e := range val {
converted[i] = convertNumericKeyword(e)
}
return converted
default:
return fmt.Sprintf("%q", val)
}
}

// skipValidationForField skips field validation (field presence) of special fields. The special fields are present
// in every (most?) documents collected by Elastic Agent, but aren't defined in any integration in `fields.yml` files.
// FIXME https://github.com/elastic/elastic-package/issues/147
Expand Down
8 changes: 7 additions & 1 deletion internal/fields/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,13 @@ func TestValidate_WithFlattenedFields(t *testing.T) {

func TestValidate_WithNumericKeywordFields(t *testing.T) {
validator, err := CreateValidatorForDirectory("testdata",
WithNumericKeywordFields([]string{"foo.code"}),
WithNumericKeywordFields([]string{
"foo.code", // Contains a number.
"foo.pid", // Contains an array of numbers.
"foo.ppid", // Contains an empty array.
"tags", // Contains an empty array, and expects normalization as array.
}),
WithSpecVersion("2.3.0"), // Needed to validate normalization.
WithDisabledDependencyManagement())
require.NoError(t, err)
require.NotNil(t, validator)
Expand Down