Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b161cb5
Update index template name
mrodm Sep 9, 2025
6469ae4
Remove outdated log message
mrodm Sep 9, 2025
fdb23e9
Extract function to create kibana policies
mrodm Sep 9, 2025
2147b14
Revert "Extract function to create kibana policies"
mrodm Sep 9, 2025
8ae0043
Update package datastream - integration policy
mrodm Sep 9, 2025
eb1450b
Add otel as suffic for dataset
mrodm Sep 9, 2025
6fe40eb
Keep package datastream / integration policy with the previous values
mrodm Sep 10, 2025
2bfebb8
Enable system test for httpcheck package
mrodm Sep 10, 2025
82f082f
httpcheck - Added field definitions
mrodm Sep 10, 2025
0a5db1b
httpcheck - replace string by keyword type
mrodm Sep 10, 2025
81df3a5
Merge upstream/main into support-system-tests-otel-input
mrodm Sep 11, 2025
68d15da
Update comments
mrodm Sep 12, 2025
fcc9f71
Skip some OTEL fields - to be validated
mrodm Sep 18, 2025
c70169d
Update index template and data stream names for system tests
mrodm Sep 18, 2025
947cb6a
Skip validation per fields in OTEL collector input
mrodm Sep 22, 2025
cc93829
Remove skip fields for OTEL
mrodm Sep 22, 2025
e9b5e34
Merge upstream/main into support-system-tests-otel-input
mrodm Sep 22, 2025
ff0213c
Skip dynamic templates without match condition
mrodm Sep 25, 2025
928852e
Replace stringInArray
mrodm Sep 26, 2025
d812670
Validate dataset fields also in OTEL
mrodm Sep 26, 2025
d0664a8
Remove duplicated assignment
mrodm Sep 26, 2025
4d347ff
Remove unnecessary else block
mrodm Sep 26, 2025
93e382b
Merge upstream/main into support-system-tests-otel-input
mrodm Sep 26, 2025
40fb639
Add warning message
mrodm Sep 29, 2025
93bd856
Update test package
mrodm Sep 29, 2025
5bd82b4
Add OTEL option when validating fields in transform
mrodm Sep 29, 2025
9d8778d
Remove all field definitions
mrodm Sep 29, 2025
dbc6b32
Restore base-fields field definitions
mrodm Sep 29, 2025
4d9935a
Remove skip test
mrodm Sep 30, 2025
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
32 changes: 18 additions & 14 deletions internal/fields/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ type Validator struct {

disabledNormalization bool

enabledOTELValidation bool

injectFieldsOptions InjectFieldsOptions
}

Expand Down Expand Up @@ -246,6 +248,14 @@ func WithInjectFieldsOptions(options InjectFieldsOptions) ValidatorOption {
}
}

// WithOTELValidation configures the validator to enable or disable OpenTelemetry specific validation.
func WithOTELValidation(otelValidation bool) ValidatorOption {
return func(v *Validator) error {
v.enabledOTELValidation = otelValidation
return nil
}
}

type packageRootFinder interface {
FindPackageRoot() (string, bool, error)
}
Expand Down Expand Up @@ -559,7 +569,13 @@ func (v *Validator) ValidateDocumentBody(body json.RawMessage) multierror.Error
// ValidateDocumentMap validates the provided document as common.MapStr.
func (v *Validator) ValidateDocumentMap(body common.MapStr) multierror.Error {
errs := v.validateDocumentValues(body)
errs = append(errs, v.validateMapElement("", body, body)...)

// If package uses OpenTelemetry Collector, skip field validation and just
// validate document values (datasets).
if !v.enabledOTELValidation {
errs = append(errs, v.validateMapElement("", body, body)...)
}

if len(errs) == 0 {
return nil
}
Expand Down Expand Up @@ -602,7 +618,7 @@ func (v *Validator) validateDocumentValues(body common.MapStr) multierror.Error
}

str, ok := valueToString(value, v.disabledNormalization)
exists := stringInArray(str, renderedExpectedDatasets)
exists := slices.Contains(renderedExpectedDatasets, str)
if !ok || !exists {
err := fmt.Errorf("field %q should have value in %q, it has \"%v\"",
datasetField, v.expectedDatasets, value)
Expand All @@ -613,18 +629,6 @@ func (v *Validator) validateDocumentValues(body common.MapStr) multierror.Error
return errs
}

func stringInArray(target string, arr []string) bool {
// Check if target is part of the array
found := false
for _, item := range arr {
if item == target {
found = true
break
}
}
return found
}

func valueToString(value any, disabledNormalization bool) (string, bool) {
if disabledNormalization {
// when synthetics mode is enabled, each field present in the document is an array
Expand Down
36 changes: 28 additions & 8 deletions internal/testrunner/runners/system/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ var (
type fieldValidationMethod int

const (
// Required to allow setting `fields` as an option via environment variable
fieldsMethod fieldValidationMethod = iota
mappingsMethod
)
Expand Down Expand Up @@ -1616,19 +1617,25 @@ func (r *tester) waitForDocs(ctx context.Context, config *testConfig, dataStream
}

func (r *tester) validateTestScenario(ctx context.Context, result *testrunner.ResultComposer, scenario *scenarioTest, config *testConfig) ([]testrunner.TestResult, error) {
logger.Info("Validating test case...")
expectedDatasets, err := r.expectedDatasets(scenario, config)
if err != nil {
return nil, err
}

// Validate fields in docs
if r.isTestUsingOTELCollectorInput(scenario.policyTemplateInput) {
logger.Warn("Validation for packages using OpenTelemetry Collector input is experimental")
}

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),
// When using the OTEL collector input, just a subset of validations are performed (e.g. check expected datasets)
fields.WithOTELValidation(r.isTestUsingOTELCollectorInput(scenario.policyTemplateInput)),
)
if err != nil {
return result.WithErrorf("creating fields validator for data stream failed (path: %s): %w", r.dataStreamPath, err)
Expand All @@ -1641,7 +1648,7 @@ func (r *tester) validateTestScenario(ctx context.Context, result *testrunner.Re
})
}

if r.fieldValidationMethod == mappingsMethod {
if !r.isTestUsingOTELCollectorInput(scenario.policyTemplateInput) && r.fieldValidationMethod == mappingsMethod {
logger.Debug("Performing validation based on mappings")
exceptionFields := listExceptionFields(scenario.docs, fieldsValidator)

Expand Down Expand Up @@ -1698,7 +1705,7 @@ func (r *tester) validateTestScenario(ctx context.Context, result *testrunner.Re
}

// Check transforms if present
if err := r.checkTransforms(ctx, config, r.pkgManifest, scenario.dataStream, scenario.syntheticEnabled); err != nil {
if err := r.checkTransforms(ctx, config, r.pkgManifest, scenario.dataStream, scenario.policyTemplateInput, scenario.syntheticEnabled); err != nil {
results, _ := result.WithError(err)
return results, nil
}
Expand Down Expand Up @@ -1817,6 +1824,19 @@ func (r *tester) runTest(ctx context.Context, config *testConfig, stackConfig st
return r.validateTestScenario(ctx, result, scenario, config)
}

func (r *tester) isTestUsingOTELCollectorInput(policyTemplateInput string) bool {
// Just supported for input packages currently
if r.pkgManifest.Type != "input" {
return false
}

if policyTemplateInput != otelCollectorInputName {
return false
}

return true
}

func dumpScenarioDocs(docs any) error {
timestamp := time.Now().Format("20060102150405")
path := filepath.Join(os.TempDir(), fmt.Sprintf("elastic-package-test-docs-dump-%s.json", timestamp))
Expand Down Expand Up @@ -1983,16 +2003,14 @@ func createInputPackageDatastream(
PolicyTemplate: policyTemplate.Name,
Enabled: true,
Vars: kibana.Vars{},
Type: policyTemplate.Input,
},
}

streamInput := policyTemplate.Input
r.Inputs[0].Type = streamInput

dataset := fmt.Sprintf("%s.%s", pkg.Name, policyTemplate.Name)
streams := []kibana.Stream{
{
ID: fmt.Sprintf("%s-%s.%s", streamInput, pkg.Name, policyTemplate.Name),
ID: fmt.Sprintf("%s-%s.%s", policyTemplate.Input, pkg.Name, policyTemplate.Name),
Enabled: true,
DataStream: kibana.DataStream{
Type: policyTemplate.Type,
Expand Down Expand Up @@ -2145,7 +2163,7 @@ func selectPolicyTemplateByName(policies []packages.PolicyTemplate, name string)
return packages.PolicyTemplate{}, fmt.Errorf("policy template %q not found", name)
}

func (r *tester) checkTransforms(ctx context.Context, config *testConfig, pkgManifest *packages.PackageManifest, dataStream string, syntheticEnabled bool) error {
func (r *tester) checkTransforms(ctx context.Context, config *testConfig, pkgManifest *packages.PackageManifest, dataStream, policyTemplateInput string, syntheticEnabled bool) error {
if config.SkipTransformValidation {
return nil
}
Expand Down Expand Up @@ -2199,6 +2217,8 @@ func (r *tester) checkTransforms(ctx context.Context, config *testConfig, pkgMan
fields.WithNumericKeywordFields(config.NumericKeywordFields),
fields.WithEnabledImportAllECSSChema(true),
fields.WithDisableNormalization(syntheticEnabled),
// When using the OTEL collector input, just a subset of validations are performed (e.g. check expected datasets)
fields.WithOTELValidation(r.isTestUsingOTELCollectorInput(policyTemplateInput)),
Comment on lines +2220 to +2221
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could input packages contain transforms ?
I think they cannot, so probably this validation based on fields for transforms could be kept as it is without disabling anything. WDYT ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They cannot contain transforms. So yeah, I guess that transform tests will be a noop even if not explicitly disabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, for input package there would not be any issue.
I was thinking if it should be kept that fields.WithOTELValidation option, if at some point integrations packages start using OTEL collector inputs.

WDYT ? Would it be better to keep it or remove it ? @jsoriano

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking if it should be kept that fields.WithOTELValidation option, if at some point integrations packages start using OTEL collector inputs.

Yes, please, keep it. When we support integrations with OTel inputs there is no reason to think that they won't support transforms.

)
if err != nil {
return fmt.Errorf("creating fields validator for data stream failed (path: %s): %w", transformRootPath, err)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
skip:
reason: Not supported system tests with input type otelcol.
link: https://github.com/elastic/elastic-package/issues/2835
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

service: web
vars:
period: 1s
endpoints:
- http://{{Hostname}}:{{Port}}
assert:
min_count: 150