From 72a66fb8d8afc7814a8b8d23ea0f41d1f3af8807 Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Wed, 28 Aug 2024 21:17:51 +0200 Subject: [PATCH 1/7] Fix matching of leaf fields for objects that don't have a wildcard --- internal/fields/validate.go | 5 +++++ internal/fields/validate_test.go | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/internal/fields/validate.go b/internal/fields/validate.go index b0611985f..34319f87b 100644 --- a/internal/fields/validate.go +++ b/internal/fields/validate.go @@ -985,6 +985,11 @@ func validSubField(def FieldDefinition, extraPart string) bool { fieldType := def.Type if def.Type == "object" && def.ObjectType != "" { fieldType = def.ObjectType + + // Match leaf fields for objects that don't have a wildcard at the end. + if parts := strings.Split(extraPart, "."); len(parts) == 2 && parts[0] == "" { + return true + } } subFields := []string{".lat", ".lon", ".values", ".counts"} diff --git a/internal/fields/validate_test.go b/internal/fields/validate_test.go index 058181004..0241e71ae 100644 --- a/internal/fields/validate_test.go +++ b/internal/fields/validate_test.go @@ -824,6 +824,12 @@ func TestCompareKeys(t *testing.T) { searchedKey: "example.foo", expected: true, }, + { + key: "example", + def: FieldDefinition{Type: "object", ObjectType: "keyword"}, + searchedKey: "example.foo", + expected: true, + }, { key: "example.foo", searchedKey: "example.*", From 40bdac29e2d156366df7b4810e89b34eb6b80216 Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Fri, 30 Aug 2024 00:02:51 +0200 Subject: [PATCH 2/7] Add test for objects --- internal/fields/testdata/fields/fields.yml | 3 +++ internal/fields/testdata/no-subobjects.json | 4 ++++ internal/fields/testdata/subobjects.json | 6 ++++++ internal/fields/validate_test.go | 19 +++++++++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 internal/fields/testdata/no-subobjects.json create mode 100644 internal/fields/testdata/subobjects.json diff --git a/internal/fields/testdata/fields/fields.yml b/internal/fields/testdata/fields/fields.yml index 1fb7459af..39a90a02c 100644 --- a/internal/fields/testdata/fields/fields.yml +++ b/internal/fields/testdata/fields/fields.yml @@ -88,3 +88,6 @@ - array - name: user.group.id type: keyword +- name: attributes + type: object + object_type: keyword diff --git a/internal/fields/testdata/no-subobjects.json b/internal/fields/testdata/no-subobjects.json new file mode 100644 index 000000000..823b3f758 --- /dev/null +++ b/internal/fields/testdata/no-subobjects.json @@ -0,0 +1,4 @@ +{ + "attributes.id": "foo", + "attributes.status": "ok" +} diff --git a/internal/fields/testdata/subobjects.json b/internal/fields/testdata/subobjects.json new file mode 100644 index 000000000..f6cba846b --- /dev/null +++ b/internal/fields/testdata/subobjects.json @@ -0,0 +1,6 @@ +{ + "attributes": { + "id": "42", + "status": "ok" + } +} diff --git a/internal/fields/validate_test.go b/internal/fields/validate_test.go index 0241e71ae..5a099cc23 100644 --- a/internal/fields/validate_test.go +++ b/internal/fields/validate_test.go @@ -64,6 +64,25 @@ func TestValidate_WithFlattenedFields(t *testing.T) { require.Empty(t, errs) } +func TestValidate_ObjectTypeWithoutWildcard(t *testing.T) { + validator, err := CreateValidatorForDirectory("testdata", + WithDisabledDependencyManagement()) + require.NoError(t, err) + require.NotNil(t, validator) + + t.Run("subobjects", func(t *testing.T) { + e := readSampleEvent(t, "testdata/subobjects.json") + errs := validator.ValidateDocumentBody(e) + require.Empty(t, errs) + }) + + t.Run("no-subobjects", func(t *testing.T) { + e := readSampleEvent(t, "testdata/no-subobjects.json") + errs := validator.ValidateDocumentBody(e) + require.Empty(t, errs) + }) +} + func TestValidate_WithNumericKeywordFields(t *testing.T) { validator, err := CreateValidatorForDirectory("testdata", WithNumericKeywordFields([]string{ From de4ed362c4cda284a735de5efc1037cb787ed47e Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Fri, 30 Aug 2024 12:50:12 +0200 Subject: [PATCH 3/7] Validate objects --- internal/fields/validate.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/internal/fields/validate.go b/internal/fields/validate.go index 34319f87b..f6f599b28 100644 --- a/internal/fields/validate.go +++ b/internal/fields/validate.go @@ -1119,7 +1119,7 @@ func (v *Validator) parseSingleElementValue(key string, definition FieldDefiniti return fmt.Errorf("the IP %q is not one of the allowed test IPs (see: https://github.com/elastic/elastic-package/blob/main/internal/fields/_static/allowed_geo_ips.txt)", valStr) } // Groups should only contain nested fields, not single values. - case "group", "nested": + case "group", "nested", "object": switch val := val.(type) { case map[string]any: // This is probably an element from an array of objects, @@ -1143,7 +1143,19 @@ func (v *Validator) parseSingleElementValue(key string, definition FieldDefiniti // The document contains a null, let's consider this like an empty array. return nil default: - return fmt.Errorf("field %q is a group of fields, it cannot store values", key) + switch { + case definition.Type == "object" && definition.ObjectType != "": + // This is the leaf element of an object without wildcards in the name, adapt the definition and try again. + definition.Name = definition.Name + ".*" + definition.Type = definition.ObjectType + definition.ObjectType = "" + return v.parseSingleElementValue(key, definition, val, doc) + case definition.Type == "object" && definition.ObjectType == "": + // Legacy mapping, abiguous definition not allowed by recent versions of the spec, ignore it. + return nil + } + + return fmt.Errorf("field %q is a group of fields of type %s, it cannot store values", key, definition.Type) } // Numbers should have been parsed as float64, otherwise they are not numbers. case "float", "long", "double": From 6f7ac5afe89bbbd2153cb5047ba1c72055bda9e8 Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Fri, 30 Aug 2024 19:34:24 +0200 Subject: [PATCH 4/7] Try to get parent definition only when all other options have been tried --- internal/fields/validate.go | 42 ++++++++++++++++++++------------ internal/fields/validate_test.go | 6 ----- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/internal/fields/validate.go b/internal/fields/validate.go index f6f599b28..2821a92a8 100644 --- a/internal/fields/validate.go +++ b/internal/fields/validate.go @@ -857,19 +857,13 @@ func isFieldTypeFlattened(key string, fieldDefinitions []FieldDefinition) bool { } func couldBeMultifield(key string, fieldDefinitions []FieldDefinition) bool { - lastDotIndex := strings.LastIndex(key, ".") - if lastDotIndex < 0 { - // Field at the root level cannot be a multifield. - return false - } - parentKey := key[:lastDotIndex] - parent := FindElementDefinition(parentKey, fieldDefinitions) + parent := findParentElementDefinition(key, fieldDefinitions) if parent == nil { // Parent is not defined, so not sure what this can be. return false } switch parent.Type { - case "", "group", "nested", "group-nested", "object": + case "", "group", "nested", "object": // Objects cannot have multifields. return false } @@ -890,8 +884,8 @@ func isArrayOfObjects(val any) bool { return false } -func findElementDefinitionForRoot(root, searchedKey string, FieldDefinitions []FieldDefinition) *FieldDefinition { - for _, def := range FieldDefinitions { +func findElementDefinitionForRoot(root, searchedKey string, fieldDefinitions []FieldDefinition) *FieldDefinition { + for _, def := range fieldDefinitions { key := strings.TrimLeft(root+"."+def.Name, ".") if compareKeys(key, def, searchedKey) { return &def @@ -907,6 +901,19 @@ func findElementDefinitionForRoot(root, searchedKey string, FieldDefinitions []F return fd } } + + if root == "" { + // No definition found, check if the parent is an object with object type. + parent := findParentElementDefinition(searchedKey, fieldDefinitions) + if parent != nil && parent.Type == "object" && parent.ObjectType != "" { + fd := *parent + fd.Name = searchedKey + fd.Type = parent.ObjectType + fd.ObjectType = "" + return &fd + } + } + return nil } @@ -915,6 +922,16 @@ func FindElementDefinition(searchedKey string, fieldDefinitions []FieldDefinitio return findElementDefinitionForRoot("", searchedKey, fieldDefinitions) } +func findParentElementDefinition(key string, fieldDefinitions []FieldDefinition) *FieldDefinition { + lastDotIndex := strings.LastIndex(key, ".") + if lastDotIndex < 0 { + // Field at the root level cannot be a multifield. + return nil + } + parentKey := key[:lastDotIndex] + return FindElementDefinition(parentKey, fieldDefinitions) +} + // compareKeys checks if `searchedKey` matches with the given `key`. `key` can contain // wildcards (`*`), that match any sequence of characters in `searchedKey` different to dots. func compareKeys(key string, def FieldDefinition, searchedKey string) bool { @@ -985,11 +1002,6 @@ func validSubField(def FieldDefinition, extraPart string) bool { fieldType := def.Type if def.Type == "object" && def.ObjectType != "" { fieldType = def.ObjectType - - // Match leaf fields for objects that don't have a wildcard at the end. - if parts := strings.Split(extraPart, "."); len(parts) == 2 && parts[0] == "" { - return true - } } subFields := []string{".lat", ".lon", ".values", ".counts"} diff --git a/internal/fields/validate_test.go b/internal/fields/validate_test.go index 5a099cc23..824d8186b 100644 --- a/internal/fields/validate_test.go +++ b/internal/fields/validate_test.go @@ -843,12 +843,6 @@ func TestCompareKeys(t *testing.T) { searchedKey: "example.foo", expected: true, }, - { - key: "example", - def: FieldDefinition{Type: "object", ObjectType: "keyword"}, - searchedKey: "example.foo", - expected: true, - }, { key: "example.foo", searchedKey: "example.*", From 4304621102c846990c51ae876c5da9dde45073dd Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Mon, 2 Sep 2024 12:15:47 +0200 Subject: [PATCH 5/7] Accept as numbers strings that can be parsed as numbers --- internal/fields/testdata/fields/fields.yml | 4 + internal/fields/testdata/stringnumbers.json | 6 + internal/fields/validate.go | 132 ++++++++---------- internal/fields/validate_test.go | 33 +++-- .../testrunner/runners/pipeline/testconfig.go | 4 + .../testrunner/runners/pipeline/tester.go | 1 + .../testrunner/runners/system/test_config.go | 4 + internal/testrunner/runners/system/tester.go | 1 + .../packages/other/string_numbers/LICENSE.txt | 93 ++++++++++++ .../other/string_numbers/changelog.yml | 6 + .../_dev/test/pipeline/test-common-config.yml | 3 + .../_dev/test/pipeline/test-example.log | 2 + .../pipeline/test-example.log-expected.json | 16 +++ .../strings/agent/stream/stream.yml.hbs | 7 + .../elasticsearch/ingest_pipeline/default.yml | 12 ++ .../strings/fields/base-fields.yml | 12 ++ .../data_stream/strings/fields/fields.yml | 4 + .../data_stream/strings/manifest.yml | 17 +++ .../other/string_numbers/docs/README.md | 84 +++++++++++ .../other/string_numbers/img/sample-logo.svg | 1 + .../string_numbers/img/sample-screenshot.png | Bin 0 -> 18849 bytes .../other/string_numbers/manifest.yml | 36 +++++ 22 files changed, 390 insertions(+), 88 deletions(-) create mode 100644 internal/fields/testdata/stringnumbers.json create mode 100644 test/packages/other/string_numbers/LICENSE.txt create mode 100644 test/packages/other/string_numbers/changelog.yml create mode 100644 test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-common-config.yml create mode 100644 test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log create mode 100644 test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log-expected.json create mode 100644 test/packages/other/string_numbers/data_stream/strings/agent/stream/stream.yml.hbs create mode 100644 test/packages/other/string_numbers/data_stream/strings/elasticsearch/ingest_pipeline/default.yml create mode 100644 test/packages/other/string_numbers/data_stream/strings/fields/base-fields.yml create mode 100644 test/packages/other/string_numbers/data_stream/strings/fields/fields.yml create mode 100644 test/packages/other/string_numbers/data_stream/strings/manifest.yml create mode 100644 test/packages/other/string_numbers/docs/README.md create mode 100644 test/packages/other/string_numbers/img/sample-logo.svg create mode 100644 test/packages/other/string_numbers/img/sample-screenshot.png create mode 100644 test/packages/other/string_numbers/manifest.yml diff --git a/internal/fields/testdata/fields/fields.yml b/internal/fields/testdata/fields/fields.yml index 39a90a02c..5ee7f1f41 100644 --- a/internal/fields/testdata/fields/fields.yml +++ b/internal/fields/testdata/fields/fields.yml @@ -17,6 +17,10 @@ value: correct - name: ip_address type: ip + - name: count + type: long + - name: metric + type: double - name: container.image.tag type: keyword normalize: diff --git a/internal/fields/testdata/stringnumbers.json b/internal/fields/testdata/stringnumbers.json new file mode 100644 index 000000000..ba099dfad --- /dev/null +++ b/internal/fields/testdata/stringnumbers.json @@ -0,0 +1,6 @@ +{ + "foo": { + "count": "42", + "metric": "2.3" + } +} diff --git a/internal/fields/validate.go b/internal/fields/validate.go index 2821a92a8..fb7cec4d6 100644 --- a/internal/fields/validate.go +++ b/internal/fields/validate.go @@ -16,6 +16,7 @@ import ( "regexp" "slices" "sort" + "strconv" "strings" "github.com/Masterminds/semver/v3" @@ -135,7 +136,12 @@ type Validator struct { expectedDatasets []string defaultNumericConversion bool - numericKeywordFields map[string]struct{} + + // fields that store keywords, but can be received as numeric types. + numericKeywordFields []string + + // fields that store numbers, but can be received as strings. + stringNumberFields []string disabledDependencyManagement bool @@ -176,10 +182,16 @@ func WithDefaultNumericConversion() ValidatorOption { // while defined as keyword or constant_keyword. func WithNumericKeywordFields(fields []string) ValidatorOption { return func(v *Validator) error { - v.numericKeywordFields = make(map[string]struct{}, len(fields)) - for _, field := range fields { - v.numericKeywordFields[field] = struct{}{} - } + v.numericKeywordFields = common.StringSlicesUnion(v.numericKeywordFields, fields) + return nil + } +} + +// WithStringNumberFields configures the validator to accept specific fields to have fields defined as numbers +// as their string representation. +func WithStringNumberFields(fields []string) ValidatorOption { + return func(v *Validator) error { + v.stringNumberFields = common.StringSlicesUnion(v.stringNumberFields, fields) return nil } } @@ -678,12 +690,6 @@ func (v *Validator) validateScalarElement(key string, val any, doc common.MapStr } } - // Convert numeric keyword fields to string for validation. - _, found := v.numericKeywordFields[key] - if (found || v.defaultNumericConversion) && isNumericKeyword(*definition, val) { - val = convertNumericKeyword(val) - } - if !v.disabledNormalization { err := v.validateExpectedNormalization(*definition, val) if err != nil { @@ -799,41 +805,6 @@ func createDocExpandingObjects(doc common.MapStr, schema []FieldDefinition) (com return newDoc, multifields, nil } -// 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 []any: - isNumber = true - loop: - for _, v := range val { - switch v.(type) { - case bool, float64: - default: - isNumber = false - break loop - } - } - } - 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 @@ -1032,12 +1003,19 @@ func validSubField(def FieldDefinition, extraPart string) bool { // parseElementValue checks that the value stored in a field matches the field definition. For // arrays it checks it for each Element. func (v *Validator) parseElementValue(key string, definition FieldDefinition, val any, doc common.MapStr) error { - err := v.parseAllElementValues(key, definition, val, doc) + // Validate types first for each element, so other checks don't need to worry about types. + err := forEachElementValue(key, definition, val, doc, v.parseSingleElementValue) if err != nil { return err } - return forEachElementValue(key, definition, val, doc, v.parseSingleElementValue) + // Perform validations that need to be done on several fields at the same time. + err = v.parseAllElementValues(key, definition, val, doc) + if err != nil { + return err + } + + return nil } // parseAllElementValues performs validations that must be done for all elements at once in @@ -1046,11 +1024,7 @@ func (v *Validator) parseAllElementValues(key string, definition FieldDefinition switch definition.Type { case "constant_keyword", "keyword", "text": if !v.specVersion.LessThan(semver2_0_0) { - strings, err := valueToStringsSlice(val) - if err != nil { - return fmt.Errorf("field %q value \"%v\" (%T): %w", key, val, val, err) - } - if err := ensureExpectedEventType(key, strings, definition, doc); err != nil { + if err := ensureExpectedEventType(key, val, definition, doc); err != nil { return err } } @@ -1064,12 +1038,24 @@ func (v *Validator) parseSingleElementValue(key string, definition FieldDefiniti return fmt.Errorf("field %q's Go type, %T, does not match the expected field type: %s (field value: %v)", key, val, definition.Type, val) } + stringValue := func() (string, bool) { + switch val := val.(type) { + case string: + return val, true + case bool, float64: + if slices.Contains(v.numericKeywordFields, key) { + return fmt.Sprintf("%v", val), true + } + } + return "", false + } + switch definition.Type { // Constant keywords can define a value in the definition, if they do, all // values stored in this field should be this one. // If a pattern is provided, it checks if the value matches. case "constant_keyword": - valStr, valid := val.(string) + valStr, valid := stringValue() if !valid { return invalidTypeError() } @@ -1086,7 +1072,7 @@ func (v *Validator) parseSingleElementValue(key string, definition FieldDefiniti // Normal text fields should be of type string. // If a pattern is provided, it checks if the value matches. case "keyword", "text": - valStr, valid := val.(string) + valStr, valid := stringValue() if !valid { return invalidTypeError() } @@ -1171,7 +1157,17 @@ func (v *Validator) parseSingleElementValue(key string, definition FieldDefiniti } // Numbers should have been parsed as float64, otherwise they are not numbers. case "float", "long", "double": - if _, valid := val.(float64); !valid { + switch val := val.(type) { + case float64: + case json.Number: + case string: + if !slices.Contains(v.stringNumberFields, key) { + return invalidTypeError() + } + if _, err := strconv.ParseFloat(val, 64); err != nil { + return invalidTypeError() + } + default: return invalidTypeError() } // All other types are considered valid not blocking validation. @@ -1271,12 +1267,10 @@ func ensureAllowedValues(key, value string, definition FieldDefinition) error { // ensureExpectedEventType validates that the document's `event.type` field is one of the expected // one for the given value. -func ensureExpectedEventType(key string, values []string, definition FieldDefinition, doc common.MapStr) error { +func ensureExpectedEventType(key string, val any, definition FieldDefinition, doc common.MapStr) error { eventTypeVal, _ := doc.GetValue("event.type") - eventTypes, err := valueToStringsSlice(eventTypeVal) - if err != nil { - return fmt.Errorf("field \"event.type\" value \"%v\" (%T): %w", eventTypeVal, eventTypeVal, err) - } + eventTypes := valueToStringsSlice(eventTypeVal) + values := valueToStringsSlice(val) var expected []string for _, value := range values { expectedForValue := definition.AllowedValues.ExpectedEventTypes(value) @@ -1295,23 +1289,19 @@ func ensureExpectedEventType(key string, values []string, definition FieldDefini return nil } -func valueToStringsSlice(value any) ([]string, error) { +func valueToStringsSlice(value any) []string { switch v := value.(type) { case nil: - return nil, nil + return nil case string: - return []string{v}, nil + return []string{v} case []any: var values []string for _, e := range v { - s, ok := e.(string) - if !ok { - return nil, fmt.Errorf("expected string or array of strings") - } - values = append(values, s) + values = append(values, fmt.Sprintf("%v", e)) } - return values, nil + return values default: - return nil, fmt.Errorf("expected string or array of strings") + return []string{fmt.Sprintf("%v", v)} } } diff --git a/internal/fields/validate_test.go b/internal/fields/validate_test.go index 824d8186b..87edd54f4 100644 --- a/internal/fields/validate_test.go +++ b/internal/fields/validate_test.go @@ -101,6 +101,22 @@ func TestValidate_WithNumericKeywordFields(t *testing.T) { require.Empty(t, errs) } +func TestValidate_WithStringNumberFields(t *testing.T) { + validator, err := CreateValidatorForDirectory("testdata", + WithStringNumberFields([]string{ + "foo.count", // Contains a number as string. + "foo.metric", // Contains a floating number as string. + }), + WithSpecVersion("2.3.0"), // Needed to validate normalization. + WithDisabledDependencyManagement()) + require.NoError(t, err) + require.NotNil(t, validator) + + e := readSampleEvent(t, "testdata/stringnumbers.json") + errs := validator.ValidateDocumentBody(e) + require.Empty(t, errs) +} + func TestValidate_WithEnabledImportAllECSSchema(t *testing.T) { finder := packageRootTestFinder{"../../test/packages/other/imported_mappings_tests"} @@ -362,14 +378,6 @@ func Test_parseElementValue(t *testing.T) { Type: "keyword", }, }, - { - key: "numeric string array to long", - value: []any{"123", "42"}, - definition: FieldDefinition{ - Type: "long", - }, - fail: true, - }, { key: "mixed numbers and strings in number array", value: []any{123, "hi"}, @@ -547,15 +555,6 @@ func Test_parseElementValue(t *testing.T) { Type: "float", }, }, - // long - { - key: "bad long", - value: "65537", - definition: FieldDefinition{ - Type: "long", - }, - fail: true, - }, // allowed values { key: "allowed values", diff --git a/internal/testrunner/runners/pipeline/testconfig.go b/internal/testrunner/runners/pipeline/testconfig.go index 84f6029ef..7823154a2 100644 --- a/internal/testrunner/runners/pipeline/testconfig.go +++ b/internal/testrunner/runners/pipeline/testconfig.go @@ -30,6 +30,10 @@ type testConfig struct { // NumericKeywordFields holds a list of fields that have keyword // type but can be ingested as numeric type. NumericKeywordFields []string `config:"numeric_keyword_fields"` + + // StringNumberFields holds a list of fields that have numeric + // types but can be ingested as strings. + StringNumberFields []string `config:"string_number_fields"` } type multiline struct { diff --git a/internal/testrunner/runners/pipeline/tester.go b/internal/testrunner/runners/pipeline/tester.go index 97ae51697..6789cec5d 100644 --- a/internal/testrunner/runners/pipeline/tester.go +++ b/internal/testrunner/runners/pipeline/tester.go @@ -335,6 +335,7 @@ func (r *tester) runTestCase(ctx context.Context, testCaseFile string, dsPath st rc.TimeElapsed = time.Since(startTime) validatorOptions = append(slices.Clone(validatorOptions), fields.WithNumericKeywordFields(tc.config.NumericKeywordFields), + fields.WithStringNumberFields(tc.config.StringNumberFields), ) fieldsValidator, err := fields.CreateValidatorForDirectory(dsPath, validatorOptions...) if err != nil { diff --git a/internal/testrunner/runners/system/test_config.go b/internal/testrunner/runners/system/test_config.go index 08dd67840..67a438b70 100644 --- a/internal/testrunner/runners/system/test_config.go +++ b/internal/testrunner/runners/system/test_config.go @@ -51,6 +51,10 @@ type testConfig struct { // type but can be ingested as numeric type. NumericKeywordFields []string `config:"numeric_keyword_fields"` + // StringNumberFields holds a list of fields that have numeric + // types but can be ingested as strings. + StringNumberFields []string `config:"string_number_fields"` + Path string `config:",ignore"` // Path of config file. ServiceVariantName string `config:",ignore"` // Name of test variant when using variants.yml. diff --git a/internal/testrunner/runners/system/tester.go b/internal/testrunner/runners/system/tester.go index 8ae04ed3d..7062b4649 100644 --- a/internal/testrunner/runners/system/tester.go +++ b/internal/testrunner/runners/system/tester.go @@ -1442,6 +1442,7 @@ func (r *tester) validateTestScenario(ctx context.Context, result *testrunner.Re fieldsValidator, err := fields.CreateValidatorForDirectory(r.dataStreamPath, fields.WithSpecVersion(r.pkgManifest.SpecVersion), fields.WithNumericKeywordFields(config.NumericKeywordFields), + fields.WithStringNumberFields(config.StringNumberFields), fields.WithExpectedDatasets(expectedDatasets), fields.WithEnabledImportAllECSSChema(true), fields.WithDisableNormalization(scenario.syntheticEnabled), diff --git a/test/packages/other/string_numbers/LICENSE.txt b/test/packages/other/string_numbers/LICENSE.txt new file mode 100644 index 000000000..809108b85 --- /dev/null +++ b/test/packages/other/string_numbers/LICENSE.txt @@ -0,0 +1,93 @@ +Elastic License 2.0 + +URL: https://www.elastic.co/licensing/elastic-license + +## Acceptance + +By using the software, you agree to all of the terms and conditions below. + +## Copyright License + +The licensor grants you a non-exclusive, royalty-free, worldwide, +non-sublicensable, non-transferable license to use, copy, distribute, make +available, and prepare derivative works of the software, in each case subject to +the limitations and conditions below. + +## Limitations + +You may not provide the software to third parties as a hosted or managed +service, where the service provides users with access to any substantial set of +the features or functionality of the software. + +You may not move, change, disable, or circumvent the license key functionality +in the software, and you may not remove or obscure any functionality in the +software that is protected by the license key. + +You may not alter, remove, or obscure any licensing, copyright, or other notices +of the licensor in the software. Any use of the licensor’s trademarks is subject +to applicable law. + +## Patents + +The licensor grants you a license, under any patent claims the licensor can +license, or becomes able to license, to make, have made, use, sell, offer for +sale, import and have imported the software, in each case subject to the +limitations and conditions in this license. This license does not cover any +patent claims that you cause to be infringed by modifications or additions to +the software. If you or your company make any written claim that the software +infringes or contributes to infringement of any patent, your patent license for +the software granted under these terms ends immediately. If your company makes +such a claim, your patent license ends immediately for work on behalf of your +company. + +## Notices + +You must ensure that anyone who gets a copy of any part of the software from you +also gets a copy of these terms. + +If you modify the software, you must include in any modified copies of the +software prominent notices stating that you have modified the software. + +## No Other Rights + +These terms do not imply any licenses other than those expressly granted in +these terms. + +## Termination + +If you use the software in violation of these terms, such use is not licensed, +and your licenses will automatically terminate. If the licensor provides you +with a notice of your violation, and you cease all violation of this license no +later than 30 days after you receive that notice, your licenses will be +reinstated retroactively. However, if you violate these terms after such +reinstatement, any additional violation of these terms will cause your licenses +to terminate automatically and permanently. + +## No Liability + +*As far as the law allows, the software comes as is, without any warranty or +condition, and the licensor will not be liable to you for any damages arising +out of these terms or the use or nature of the software, under any kind of +legal claim.* + +## Definitions + +The **licensor** is the entity offering these terms, and the **software** is the +software the licensor makes available under these terms, including any portion +of it. + +**you** refers to the individual or entity agreeing to these terms. + +**your company** is any legal entity, sole proprietorship, or other kind of +organization that you work for, plus all organizations that have control over, +are under the control of, or are under common control with that +organization. **control** means ownership of substantially all the assets of an +entity, or the power to direct its management and policies by vote, contract, or +otherwise. Control can be direct or indirect. + +**your licenses** are all the licenses granted to you for the software under +these terms. + +**use** means anything you do with the software requiring one of your licenses. + +**trademark** means trademarks, service marks, and similar rights. diff --git a/test/packages/other/string_numbers/changelog.yml b/test/packages/other/string_numbers/changelog.yml new file mode 100644 index 000000000..bb0320a52 --- /dev/null +++ b/test/packages/other/string_numbers/changelog.yml @@ -0,0 +1,6 @@ +# newer versions go on top +- version: "0.0.1" + changes: + - description: Initial draft of the package + type: enhancement + link: https://github.com/elastic/integrations/pull/1 # FIXME Replace with the real PR link diff --git a/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-common-config.yml b/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-common-config.yml new file mode 100644 index 000000000..b3a484311 --- /dev/null +++ b/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-common-config.yml @@ -0,0 +1,3 @@ +string_number_fields: + - "example.count" + - "example.metric" diff --git a/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log b/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log new file mode 100644 index 000000000..8261e6f72 --- /dev/null +++ b/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log @@ -0,0 +1,2 @@ +34 43.2 +0 1234 diff --git a/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log-expected.json b/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log-expected.json new file mode 100644 index 000000000..c44983ac1 --- /dev/null +++ b/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log-expected.json @@ -0,0 +1,16 @@ +{ + "expected": [ + { + "example": { + "count": "34", + "metric": "43.2" + } + }, + { + "example": { + "count": "0", + "metric": "1234" + } + } + ] +} \ No newline at end of file diff --git a/test/packages/other/string_numbers/data_stream/strings/agent/stream/stream.yml.hbs b/test/packages/other/string_numbers/data_stream/strings/agent/stream/stream.yml.hbs new file mode 100644 index 000000000..5845510de --- /dev/null +++ b/test/packages/other/string_numbers/data_stream/strings/agent/stream/stream.yml.hbs @@ -0,0 +1,7 @@ +paths: +{{#each paths as |path i|}} + - {{path}} +{{/each}} +exclude_files: [".gz$"] +processors: + - add_locale: ~ diff --git a/test/packages/other/string_numbers/data_stream/strings/elasticsearch/ingest_pipeline/default.yml b/test/packages/other/string_numbers/data_stream/strings/elasticsearch/ingest_pipeline/default.yml new file mode 100644 index 000000000..178b453b4 --- /dev/null +++ b/test/packages/other/string_numbers/data_stream/strings/elasticsearch/ingest_pipeline/default.yml @@ -0,0 +1,12 @@ +--- +description: Pipeline for processing sample logs +processors: +- dissect: + field: message + pattern: "%{example.count} %{example.metric}" +- remove: + field: message +on_failure: +- set: + field: error.message + value: '{{ _ingest.on_failure_message }}' diff --git a/test/packages/other/string_numbers/data_stream/strings/fields/base-fields.yml b/test/packages/other/string_numbers/data_stream/strings/fields/base-fields.yml new file mode 100644 index 000000000..7c798f453 --- /dev/null +++ b/test/packages/other/string_numbers/data_stream/strings/fields/base-fields.yml @@ -0,0 +1,12 @@ +- name: data_stream.type + type: constant_keyword + description: Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: Data stream namespace. +- name: '@timestamp' + type: date + description: Event timestamp. diff --git a/test/packages/other/string_numbers/data_stream/strings/fields/fields.yml b/test/packages/other/string_numbers/data_stream/strings/fields/fields.yml new file mode 100644 index 000000000..fdad1423b --- /dev/null +++ b/test/packages/other/string_numbers/data_stream/strings/fields/fields.yml @@ -0,0 +1,4 @@ +- name: example.count + type: long +- name: example.metric + type: double diff --git a/test/packages/other/string_numbers/data_stream/strings/manifest.yml b/test/packages/other/string_numbers/data_stream/strings/manifest.yml new file mode 100644 index 000000000..18c138fa1 --- /dev/null +++ b/test/packages/other/string_numbers/data_stream/strings/manifest.yml @@ -0,0 +1,17 @@ +title: "Strings" +type: logs +streams: + - input: logfile + title: Sample logs + description: Collect sample logs + vars: + - name: paths + type: text + title: Paths + multi: true + default: + - /var/log/*.log +elasticsearch: + index_template: + mappings: + subobjects: false diff --git a/test/packages/other/string_numbers/docs/README.md b/test/packages/other/string_numbers/docs/README.md new file mode 100644 index 000000000..158ddaca4 --- /dev/null +++ b/test/packages/other/string_numbers/docs/README.md @@ -0,0 +1,84 @@ + + + +# "String numbers" + + + +## Data streams + + + + + + + + + + + +## Requirements + +You need Elasticsearch for storing and searching your data and Kibana for visualizing and managing it. +You can use our hosted Elasticsearch Service on Elastic Cloud, which is recommended, or self-manage the Elastic Stack on your own hardware. + + + +## Setup + + + +For step-by-step instructions on how to set up an integration, see the +[Getting started](https://www.elastic.co/guide/en/welcome-to-elastic/current/getting-started-observability.html) guide. + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/packages/other/string_numbers/img/sample-logo.svg b/test/packages/other/string_numbers/img/sample-logo.svg new file mode 100644 index 000000000..6268dd88f --- /dev/null +++ b/test/packages/other/string_numbers/img/sample-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/packages/other/string_numbers/img/sample-screenshot.png b/test/packages/other/string_numbers/img/sample-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..d7a56a3ecc078c38636698cefba33f86291dd178 GIT binary patch literal 18849 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

}qal5$moSACwfNXLXG5|3R0AtBcN` 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 literal 0 HcmV?d00001 diff --git a/test/packages/other/string_numbers/manifest.yml b/test/packages/other/string_numbers/manifest.yml new file mode 100644 index 000000000..c4caaea11 --- /dev/null +++ b/test/packages/other/string_numbers/manifest.yml @@ -0,0 +1,36 @@ +format_version: 3.2.1 +name: string_numbers +title: "Package to test pipelines with documents with numbers sent as strings." +version: 0.0.1 +source: + license: "Elastic-2.0" +description: "Package to test pipelines with documents with numbers sent as strings." +type: integration +categories: + - custom +conditions: + kibana: + version: "^8.15.0" + elastic: + subscription: "basic" +screenshots: + - src: /img/sample-screenshot.png + title: Sample screenshot + size: 600x600 + type: image/png +icons: + - src: /img/sample-logo.svg + title: Sample logo + size: 32x32 + type: image/svg+xml +policy_templates: + - name: sample + title: Sample logs + description: Collect sample logs + inputs: + - type: logfile + title: Collect sample logs from instances + description: Collecting sample logs +owner: + github: elastic/ecosystem + type: elastic From 9fc3af24972777ab59457ac812cac4da5e88ad88 Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Mon, 2 Sep 2024 15:41:29 +0200 Subject: [PATCH 6/7] Revert "Accept as numbers strings that can be parsed as numbers" This reverts commit 4304621102c846990c51ae876c5da9dde45073dd. --- internal/fields/testdata/fields/fields.yml | 4 - internal/fields/testdata/stringnumbers.json | 6 - internal/fields/validate.go | 132 ++++++++++-------- internal/fields/validate_test.go | 33 ++--- .../testrunner/runners/pipeline/testconfig.go | 4 - .../testrunner/runners/pipeline/tester.go | 1 - .../testrunner/runners/system/test_config.go | 4 - internal/testrunner/runners/system/tester.go | 1 - .../packages/other/string_numbers/LICENSE.txt | 93 ------------ .../other/string_numbers/changelog.yml | 6 - .../_dev/test/pipeline/test-common-config.yml | 3 - .../_dev/test/pipeline/test-example.log | 2 - .../pipeline/test-example.log-expected.json | 16 --- .../strings/agent/stream/stream.yml.hbs | 7 - .../elasticsearch/ingest_pipeline/default.yml | 12 -- .../strings/fields/base-fields.yml | 12 -- .../data_stream/strings/fields/fields.yml | 4 - .../data_stream/strings/manifest.yml | 17 --- .../other/string_numbers/docs/README.md | 84 ----------- .../other/string_numbers/img/sample-logo.svg | 1 - .../string_numbers/img/sample-screenshot.png | Bin 18849 -> 0 bytes .../other/string_numbers/manifest.yml | 36 ----- 22 files changed, 88 insertions(+), 390 deletions(-) delete mode 100644 internal/fields/testdata/stringnumbers.json delete mode 100644 test/packages/other/string_numbers/LICENSE.txt delete mode 100644 test/packages/other/string_numbers/changelog.yml delete mode 100644 test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-common-config.yml delete mode 100644 test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log delete mode 100644 test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log-expected.json delete mode 100644 test/packages/other/string_numbers/data_stream/strings/agent/stream/stream.yml.hbs delete mode 100644 test/packages/other/string_numbers/data_stream/strings/elasticsearch/ingest_pipeline/default.yml delete mode 100644 test/packages/other/string_numbers/data_stream/strings/fields/base-fields.yml delete mode 100644 test/packages/other/string_numbers/data_stream/strings/fields/fields.yml delete mode 100644 test/packages/other/string_numbers/data_stream/strings/manifest.yml delete mode 100644 test/packages/other/string_numbers/docs/README.md delete mode 100644 test/packages/other/string_numbers/img/sample-logo.svg delete mode 100644 test/packages/other/string_numbers/img/sample-screenshot.png delete mode 100644 test/packages/other/string_numbers/manifest.yml diff --git a/internal/fields/testdata/fields/fields.yml b/internal/fields/testdata/fields/fields.yml index 5ee7f1f41..39a90a02c 100644 --- a/internal/fields/testdata/fields/fields.yml +++ b/internal/fields/testdata/fields/fields.yml @@ -17,10 +17,6 @@ value: correct - name: ip_address type: ip - - name: count - type: long - - name: metric - type: double - name: container.image.tag type: keyword normalize: diff --git a/internal/fields/testdata/stringnumbers.json b/internal/fields/testdata/stringnumbers.json deleted file mode 100644 index ba099dfad..000000000 --- a/internal/fields/testdata/stringnumbers.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "foo": { - "count": "42", - "metric": "2.3" - } -} diff --git a/internal/fields/validate.go b/internal/fields/validate.go index fb7cec4d6..2821a92a8 100644 --- a/internal/fields/validate.go +++ b/internal/fields/validate.go @@ -16,7 +16,6 @@ import ( "regexp" "slices" "sort" - "strconv" "strings" "github.com/Masterminds/semver/v3" @@ -136,12 +135,7 @@ type Validator struct { expectedDatasets []string defaultNumericConversion bool - - // fields that store keywords, but can be received as numeric types. - numericKeywordFields []string - - // fields that store numbers, but can be received as strings. - stringNumberFields []string + numericKeywordFields map[string]struct{} disabledDependencyManagement bool @@ -182,16 +176,10 @@ func WithDefaultNumericConversion() ValidatorOption { // while defined as keyword or constant_keyword. func WithNumericKeywordFields(fields []string) ValidatorOption { return func(v *Validator) error { - v.numericKeywordFields = common.StringSlicesUnion(v.numericKeywordFields, fields) - return nil - } -} - -// WithStringNumberFields configures the validator to accept specific fields to have fields defined as numbers -// as their string representation. -func WithStringNumberFields(fields []string) ValidatorOption { - return func(v *Validator) error { - v.stringNumberFields = common.StringSlicesUnion(v.stringNumberFields, fields) + v.numericKeywordFields = make(map[string]struct{}, len(fields)) + for _, field := range fields { + v.numericKeywordFields[field] = struct{}{} + } return nil } } @@ -690,6 +678,12 @@ func (v *Validator) validateScalarElement(key string, val any, doc common.MapStr } } + // Convert numeric keyword fields to string for validation. + _, found := v.numericKeywordFields[key] + if (found || v.defaultNumericConversion) && isNumericKeyword(*definition, val) { + val = convertNumericKeyword(val) + } + if !v.disabledNormalization { err := v.validateExpectedNormalization(*definition, val) if err != nil { @@ -805,6 +799,41 @@ func createDocExpandingObjects(doc common.MapStr, schema []FieldDefinition) (com return newDoc, multifields, nil } +// 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 []any: + isNumber = true + loop: + for _, v := range val { + switch v.(type) { + case bool, float64: + default: + isNumber = false + break loop + } + } + } + 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 @@ -1003,19 +1032,12 @@ func validSubField(def FieldDefinition, extraPart string) bool { // parseElementValue checks that the value stored in a field matches the field definition. For // arrays it checks it for each Element. func (v *Validator) parseElementValue(key string, definition FieldDefinition, val any, doc common.MapStr) error { - // Validate types first for each element, so other checks don't need to worry about types. - err := forEachElementValue(key, definition, val, doc, v.parseSingleElementValue) + err := v.parseAllElementValues(key, definition, val, doc) if err != nil { return err } - // Perform validations that need to be done on several fields at the same time. - err = v.parseAllElementValues(key, definition, val, doc) - if err != nil { - return err - } - - return nil + return forEachElementValue(key, definition, val, doc, v.parseSingleElementValue) } // parseAllElementValues performs validations that must be done for all elements at once in @@ -1024,7 +1046,11 @@ func (v *Validator) parseAllElementValues(key string, definition FieldDefinition switch definition.Type { case "constant_keyword", "keyword", "text": if !v.specVersion.LessThan(semver2_0_0) { - if err := ensureExpectedEventType(key, val, definition, doc); err != nil { + strings, err := valueToStringsSlice(val) + if err != nil { + return fmt.Errorf("field %q value \"%v\" (%T): %w", key, val, val, err) + } + if err := ensureExpectedEventType(key, strings, definition, doc); err != nil { return err } } @@ -1038,24 +1064,12 @@ func (v *Validator) parseSingleElementValue(key string, definition FieldDefiniti return fmt.Errorf("field %q's Go type, %T, does not match the expected field type: %s (field value: %v)", key, val, definition.Type, val) } - stringValue := func() (string, bool) { - switch val := val.(type) { - case string: - return val, true - case bool, float64: - if slices.Contains(v.numericKeywordFields, key) { - return fmt.Sprintf("%v", val), true - } - } - return "", false - } - switch definition.Type { // Constant keywords can define a value in the definition, if they do, all // values stored in this field should be this one. // If a pattern is provided, it checks if the value matches. case "constant_keyword": - valStr, valid := stringValue() + valStr, valid := val.(string) if !valid { return invalidTypeError() } @@ -1072,7 +1086,7 @@ func (v *Validator) parseSingleElementValue(key string, definition FieldDefiniti // Normal text fields should be of type string. // If a pattern is provided, it checks if the value matches. case "keyword", "text": - valStr, valid := stringValue() + valStr, valid := val.(string) if !valid { return invalidTypeError() } @@ -1157,17 +1171,7 @@ func (v *Validator) parseSingleElementValue(key string, definition FieldDefiniti } // Numbers should have been parsed as float64, otherwise they are not numbers. case "float", "long", "double": - switch val := val.(type) { - case float64: - case json.Number: - case string: - if !slices.Contains(v.stringNumberFields, key) { - return invalidTypeError() - } - if _, err := strconv.ParseFloat(val, 64); err != nil { - return invalidTypeError() - } - default: + if _, valid := val.(float64); !valid { return invalidTypeError() } // All other types are considered valid not blocking validation. @@ -1267,10 +1271,12 @@ func ensureAllowedValues(key, value string, definition FieldDefinition) error { // ensureExpectedEventType validates that the document's `event.type` field is one of the expected // one for the given value. -func ensureExpectedEventType(key string, val any, definition FieldDefinition, doc common.MapStr) error { +func ensureExpectedEventType(key string, values []string, definition FieldDefinition, doc common.MapStr) error { eventTypeVal, _ := doc.GetValue("event.type") - eventTypes := valueToStringsSlice(eventTypeVal) - values := valueToStringsSlice(val) + eventTypes, err := valueToStringsSlice(eventTypeVal) + if err != nil { + return fmt.Errorf("field \"event.type\" value \"%v\" (%T): %w", eventTypeVal, eventTypeVal, err) + } var expected []string for _, value := range values { expectedForValue := definition.AllowedValues.ExpectedEventTypes(value) @@ -1289,19 +1295,23 @@ func ensureExpectedEventType(key string, val any, definition FieldDefinition, do return nil } -func valueToStringsSlice(value any) []string { +func valueToStringsSlice(value any) ([]string, error) { switch v := value.(type) { case nil: - return nil + return nil, nil case string: - return []string{v} + return []string{v}, nil case []any: var values []string for _, e := range v { - values = append(values, fmt.Sprintf("%v", e)) + s, ok := e.(string) + if !ok { + return nil, fmt.Errorf("expected string or array of strings") + } + values = append(values, s) } - return values + return values, nil default: - return []string{fmt.Sprintf("%v", v)} + return nil, fmt.Errorf("expected string or array of strings") } } diff --git a/internal/fields/validate_test.go b/internal/fields/validate_test.go index 87edd54f4..824d8186b 100644 --- a/internal/fields/validate_test.go +++ b/internal/fields/validate_test.go @@ -101,22 +101,6 @@ func TestValidate_WithNumericKeywordFields(t *testing.T) { require.Empty(t, errs) } -func TestValidate_WithStringNumberFields(t *testing.T) { - validator, err := CreateValidatorForDirectory("testdata", - WithStringNumberFields([]string{ - "foo.count", // Contains a number as string. - "foo.metric", // Contains a floating number as string. - }), - WithSpecVersion("2.3.0"), // Needed to validate normalization. - WithDisabledDependencyManagement()) - require.NoError(t, err) - require.NotNil(t, validator) - - e := readSampleEvent(t, "testdata/stringnumbers.json") - errs := validator.ValidateDocumentBody(e) - require.Empty(t, errs) -} - func TestValidate_WithEnabledImportAllECSSchema(t *testing.T) { finder := packageRootTestFinder{"../../test/packages/other/imported_mappings_tests"} @@ -378,6 +362,14 @@ func Test_parseElementValue(t *testing.T) { Type: "keyword", }, }, + { + key: "numeric string array to long", + value: []any{"123", "42"}, + definition: FieldDefinition{ + Type: "long", + }, + fail: true, + }, { key: "mixed numbers and strings in number array", value: []any{123, "hi"}, @@ -555,6 +547,15 @@ func Test_parseElementValue(t *testing.T) { Type: "float", }, }, + // long + { + key: "bad long", + value: "65537", + definition: FieldDefinition{ + Type: "long", + }, + fail: true, + }, // allowed values { key: "allowed values", diff --git a/internal/testrunner/runners/pipeline/testconfig.go b/internal/testrunner/runners/pipeline/testconfig.go index 7823154a2..84f6029ef 100644 --- a/internal/testrunner/runners/pipeline/testconfig.go +++ b/internal/testrunner/runners/pipeline/testconfig.go @@ -30,10 +30,6 @@ type testConfig struct { // NumericKeywordFields holds a list of fields that have keyword // type but can be ingested as numeric type. NumericKeywordFields []string `config:"numeric_keyword_fields"` - - // StringNumberFields holds a list of fields that have numeric - // types but can be ingested as strings. - StringNumberFields []string `config:"string_number_fields"` } type multiline struct { diff --git a/internal/testrunner/runners/pipeline/tester.go b/internal/testrunner/runners/pipeline/tester.go index 6789cec5d..97ae51697 100644 --- a/internal/testrunner/runners/pipeline/tester.go +++ b/internal/testrunner/runners/pipeline/tester.go @@ -335,7 +335,6 @@ func (r *tester) runTestCase(ctx context.Context, testCaseFile string, dsPath st rc.TimeElapsed = time.Since(startTime) validatorOptions = append(slices.Clone(validatorOptions), fields.WithNumericKeywordFields(tc.config.NumericKeywordFields), - fields.WithStringNumberFields(tc.config.StringNumberFields), ) fieldsValidator, err := fields.CreateValidatorForDirectory(dsPath, validatorOptions...) if err != nil { diff --git a/internal/testrunner/runners/system/test_config.go b/internal/testrunner/runners/system/test_config.go index 67a438b70..08dd67840 100644 --- a/internal/testrunner/runners/system/test_config.go +++ b/internal/testrunner/runners/system/test_config.go @@ -51,10 +51,6 @@ type testConfig struct { // type but can be ingested as numeric type. NumericKeywordFields []string `config:"numeric_keyword_fields"` - // StringNumberFields holds a list of fields that have numeric - // types but can be ingested as strings. - StringNumberFields []string `config:"string_number_fields"` - Path string `config:",ignore"` // Path of config file. ServiceVariantName string `config:",ignore"` // Name of test variant when using variants.yml. diff --git a/internal/testrunner/runners/system/tester.go b/internal/testrunner/runners/system/tester.go index 7062b4649..8ae04ed3d 100644 --- a/internal/testrunner/runners/system/tester.go +++ b/internal/testrunner/runners/system/tester.go @@ -1442,7 +1442,6 @@ func (r *tester) validateTestScenario(ctx context.Context, result *testrunner.Re fieldsValidator, err := fields.CreateValidatorForDirectory(r.dataStreamPath, fields.WithSpecVersion(r.pkgManifest.SpecVersion), fields.WithNumericKeywordFields(config.NumericKeywordFields), - fields.WithStringNumberFields(config.StringNumberFields), fields.WithExpectedDatasets(expectedDatasets), fields.WithEnabledImportAllECSSChema(true), fields.WithDisableNormalization(scenario.syntheticEnabled), diff --git a/test/packages/other/string_numbers/LICENSE.txt b/test/packages/other/string_numbers/LICENSE.txt deleted file mode 100644 index 809108b85..000000000 --- a/test/packages/other/string_numbers/LICENSE.txt +++ /dev/null @@ -1,93 +0,0 @@ -Elastic License 2.0 - -URL: https://www.elastic.co/licensing/elastic-license - -## Acceptance - -By using the software, you agree to all of the terms and conditions below. - -## Copyright License - -The licensor grants you a non-exclusive, royalty-free, worldwide, -non-sublicensable, non-transferable license to use, copy, distribute, make -available, and prepare derivative works of the software, in each case subject to -the limitations and conditions below. - -## Limitations - -You may not provide the software to third parties as a hosted or managed -service, where the service provides users with access to any substantial set of -the features or functionality of the software. - -You may not move, change, disable, or circumvent the license key functionality -in the software, and you may not remove or obscure any functionality in the -software that is protected by the license key. - -You may not alter, remove, or obscure any licensing, copyright, or other notices -of the licensor in the software. Any use of the licensor’s trademarks is subject -to applicable law. - -## Patents - -The licensor grants you a license, under any patent claims the licensor can -license, or becomes able to license, to make, have made, use, sell, offer for -sale, import and have imported the software, in each case subject to the -limitations and conditions in this license. This license does not cover any -patent claims that you cause to be infringed by modifications or additions to -the software. If you or your company make any written claim that the software -infringes or contributes to infringement of any patent, your patent license for -the software granted under these terms ends immediately. If your company makes -such a claim, your patent license ends immediately for work on behalf of your -company. - -## Notices - -You must ensure that anyone who gets a copy of any part of the software from you -also gets a copy of these terms. - -If you modify the software, you must include in any modified copies of the -software prominent notices stating that you have modified the software. - -## No Other Rights - -These terms do not imply any licenses other than those expressly granted in -these terms. - -## Termination - -If you use the software in violation of these terms, such use is not licensed, -and your licenses will automatically terminate. If the licensor provides you -with a notice of your violation, and you cease all violation of this license no -later than 30 days after you receive that notice, your licenses will be -reinstated retroactively. However, if you violate these terms after such -reinstatement, any additional violation of these terms will cause your licenses -to terminate automatically and permanently. - -## No Liability - -*As far as the law allows, the software comes as is, without any warranty or -condition, and the licensor will not be liable to you for any damages arising -out of these terms or the use or nature of the software, under any kind of -legal claim.* - -## Definitions - -The **licensor** is the entity offering these terms, and the **software** is the -software the licensor makes available under these terms, including any portion -of it. - -**you** refers to the individual or entity agreeing to these terms. - -**your company** is any legal entity, sole proprietorship, or other kind of -organization that you work for, plus all organizations that have control over, -are under the control of, or are under common control with that -organization. **control** means ownership of substantially all the assets of an -entity, or the power to direct its management and policies by vote, contract, or -otherwise. Control can be direct or indirect. - -**your licenses** are all the licenses granted to you for the software under -these terms. - -**use** means anything you do with the software requiring one of your licenses. - -**trademark** means trademarks, service marks, and similar rights. diff --git a/test/packages/other/string_numbers/changelog.yml b/test/packages/other/string_numbers/changelog.yml deleted file mode 100644 index bb0320a52..000000000 --- a/test/packages/other/string_numbers/changelog.yml +++ /dev/null @@ -1,6 +0,0 @@ -# newer versions go on top -- version: "0.0.1" - changes: - - description: Initial draft of the package - type: enhancement - link: https://github.com/elastic/integrations/pull/1 # FIXME Replace with the real PR link diff --git a/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-common-config.yml b/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-common-config.yml deleted file mode 100644 index b3a484311..000000000 --- a/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-common-config.yml +++ /dev/null @@ -1,3 +0,0 @@ -string_number_fields: - - "example.count" - - "example.metric" diff --git a/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log b/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log deleted file mode 100644 index 8261e6f72..000000000 --- a/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log +++ /dev/null @@ -1,2 +0,0 @@ -34 43.2 -0 1234 diff --git a/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log-expected.json b/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log-expected.json deleted file mode 100644 index c44983ac1..000000000 --- a/test/packages/other/string_numbers/data_stream/strings/_dev/test/pipeline/test-example.log-expected.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "expected": [ - { - "example": { - "count": "34", - "metric": "43.2" - } - }, - { - "example": { - "count": "0", - "metric": "1234" - } - } - ] -} \ No newline at end of file diff --git a/test/packages/other/string_numbers/data_stream/strings/agent/stream/stream.yml.hbs b/test/packages/other/string_numbers/data_stream/strings/agent/stream/stream.yml.hbs deleted file mode 100644 index 5845510de..000000000 --- a/test/packages/other/string_numbers/data_stream/strings/agent/stream/stream.yml.hbs +++ /dev/null @@ -1,7 +0,0 @@ -paths: -{{#each paths as |path i|}} - - {{path}} -{{/each}} -exclude_files: [".gz$"] -processors: - - add_locale: ~ diff --git a/test/packages/other/string_numbers/data_stream/strings/elasticsearch/ingest_pipeline/default.yml b/test/packages/other/string_numbers/data_stream/strings/elasticsearch/ingest_pipeline/default.yml deleted file mode 100644 index 178b453b4..000000000 --- a/test/packages/other/string_numbers/data_stream/strings/elasticsearch/ingest_pipeline/default.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -description: Pipeline for processing sample logs -processors: -- dissect: - field: message - pattern: "%{example.count} %{example.metric}" -- remove: - field: message -on_failure: -- set: - field: error.message - value: '{{ _ingest.on_failure_message }}' diff --git a/test/packages/other/string_numbers/data_stream/strings/fields/base-fields.yml b/test/packages/other/string_numbers/data_stream/strings/fields/base-fields.yml deleted file mode 100644 index 7c798f453..000000000 --- a/test/packages/other/string_numbers/data_stream/strings/fields/base-fields.yml +++ /dev/null @@ -1,12 +0,0 @@ -- name: data_stream.type - type: constant_keyword - description: Data stream type. -- name: data_stream.dataset - type: constant_keyword - description: Data stream dataset. -- name: data_stream.namespace - type: constant_keyword - description: Data stream namespace. -- name: '@timestamp' - type: date - description: Event timestamp. diff --git a/test/packages/other/string_numbers/data_stream/strings/fields/fields.yml b/test/packages/other/string_numbers/data_stream/strings/fields/fields.yml deleted file mode 100644 index fdad1423b..000000000 --- a/test/packages/other/string_numbers/data_stream/strings/fields/fields.yml +++ /dev/null @@ -1,4 +0,0 @@ -- name: example.count - type: long -- name: example.metric - type: double diff --git a/test/packages/other/string_numbers/data_stream/strings/manifest.yml b/test/packages/other/string_numbers/data_stream/strings/manifest.yml deleted file mode 100644 index 18c138fa1..000000000 --- a/test/packages/other/string_numbers/data_stream/strings/manifest.yml +++ /dev/null @@ -1,17 +0,0 @@ -title: "Strings" -type: logs -streams: - - input: logfile - title: Sample logs - description: Collect sample logs - vars: - - name: paths - type: text - title: Paths - multi: true - default: - - /var/log/*.log -elasticsearch: - index_template: - mappings: - subobjects: false diff --git a/test/packages/other/string_numbers/docs/README.md b/test/packages/other/string_numbers/docs/README.md deleted file mode 100644 index 158ddaca4..000000000 --- a/test/packages/other/string_numbers/docs/README.md +++ /dev/null @@ -1,84 +0,0 @@ - - - -# "String numbers" - - - -## Data streams - - - - - - - - - - - -## Requirements - -You need Elasticsearch for storing and searching your data and Kibana for visualizing and managing it. -You can use our hosted Elasticsearch Service on Elastic Cloud, which is recommended, or self-manage the Elastic Stack on your own hardware. - - - -## Setup - - - -For step-by-step instructions on how to set up an integration, see the -[Getting started](https://www.elastic.co/guide/en/welcome-to-elastic/current/getting-started-observability.html) guide. - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/packages/other/string_numbers/img/sample-logo.svg b/test/packages/other/string_numbers/img/sample-logo.svg deleted file mode 100644 index 6268dd88f..000000000 --- a/test/packages/other/string_numbers/img/sample-logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/test/packages/other/string_numbers/img/sample-screenshot.png b/test/packages/other/string_numbers/img/sample-screenshot.png deleted file mode 100644 index d7a56a3ecc078c38636698cefba33f86291dd178..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18849 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

}qal5$moSACwfNXLXG5|3R0AtBcN` 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 diff --git a/test/packages/other/string_numbers/manifest.yml b/test/packages/other/string_numbers/manifest.yml deleted file mode 100644 index c4caaea11..000000000 --- a/test/packages/other/string_numbers/manifest.yml +++ /dev/null @@ -1,36 +0,0 @@ -format_version: 3.2.1 -name: string_numbers -title: "Package to test pipelines with documents with numbers sent as strings." -version: 0.0.1 -source: - license: "Elastic-2.0" -description: "Package to test pipelines with documents with numbers sent as strings." -type: integration -categories: - - custom -conditions: - kibana: - version: "^8.15.0" - elastic: - subscription: "basic" -screenshots: - - src: /img/sample-screenshot.png - title: Sample screenshot - size: 600x600 - type: image/png -icons: - - src: /img/sample-logo.svg - title: Sample logo - size: 32x32 - type: image/svg+xml -policy_templates: - - name: sample - title: Sample logs - description: Collect sample logs - inputs: - - type: logfile - title: Collect sample logs from instances - description: Collecting sample logs -owner: - github: elastic/ecosystem - type: elastic From 0d1db04dbd87e34329ea5bb15417b8dca6e4dfc6 Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Wed, 4 Sep 2024 12:54:43 +0200 Subject: [PATCH 7/7] Fix comment --- internal/fields/validate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/fields/validate.go b/internal/fields/validate.go index 2713b6cd3..d7a6b518f 100644 --- a/internal/fields/validate.go +++ b/internal/fields/validate.go @@ -1149,7 +1149,7 @@ func (v *Validator) parseSingleElementValue(key string, definition FieldDefiniti definition.ObjectType = "" return v.parseSingleElementValue(key, definition, val, doc) case definition.Type == "object" && definition.ObjectType == "": - // Legacy mapping, abiguous definition not allowed by recent versions of the spec, ignore it. + // Legacy mapping, ambiguous definition not allowed by recent versions of the spec, ignore it. return nil }