Skip to content

Conversation

@mrodm
Copy link
Contributor

@mrodm mrodm commented Sep 4, 2025

Supersedes #2799
Relates #2835
Relates elastic/kibana#227673

Add support to run policy tests in input packages defining a policy template with the input type otelcol. Continuing the work done in #2799

In order to support policy tests in those packages, it is needed to add filters to remove the ids that may appear in policies with OTel configuration. Some examples:

receivers: httpcheck/b0f518d6-4e2d-4c5d-bda7-f9808df537b7: collection_interval: 1m targets: - endpoints: - https://epr.elastic.co method: GET secret_references: [] service: pipelines: logs: receivers: - httpcheck/b0f518d6-4e2d-4c5d-bda7-f9808df537b7

This PR adds a new test package httpcheck that includes this new input type (copied from elastic/integrations#14315).

In order to test this new input type, this PR also enables the feature flag enableOtelIntegration in Kibana configuration file. That feature flag was added in elastic/kibana#227673.

Examples:

  • Stack versions between 8.7.0 and 8.10.0-SNAPSHOT
xpack.fleet.enableExperimental: [ # Enable experimental toggles in Fleet UI "experimentalDataStreamSettings"]
  • Stack versions starting in 9.2.0-SNAPSHOT:
xpack.fleet.enableExperimental: [ # Support for otelcol input "enableOtelIntegrations"]
  • Stack versions between 8.3.0 and 8.7.0
xpack.fleet.enableExperimental: []
  • Older stack versions (<8.3.0) do not define this configuration key.

How to test this PR locally

elastic-package stack up -v -d --version 9.2.0-SNAPSHOT elastic-package -C test/packages/parallel/httpcheck test policy -v elastic-package stack down -v
@mrodm mrodm self-assigned this Sep 4, 2025
@@ -0,0 +1 @@
9.2.0-SNAPSHOT
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Forced to run this package with 9.2.0-SNAPSHOT.

This should be removed once the default version is 9.2.0 or higher.

Comment on lines +337 to +343
receivers:
httpcheck/b0f518d6-4e2d-4c5d-bda7-f9808df537b7:
collection_interval: 1m
targets:
- endpoints:
- https://epr.elastic.co
method: GET
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jsoriano in these policies, could it be more than one receiver/exporter/extensions/processors?
Focusing on receiver as example, if there is another receiver defined, would it start also with httpcheck ?

receivers: httpcheck/b0f518d6-4e2d-4c5d-bda7-f9808df537b7: collection_interval: 1m targets: - endpoints: - https://epr.elastic.co method: GET httpcheck/b0f518d6-4e2d-4c5d-bda7-11111111111: collection_interval: 2m targets: - endpoints: - https://example.com method: GET 

If that could happen, the resulting yaml would contain just one receiver httpcheck/componentid

Copy link
Member

Choose a reason for hiding this comment

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

In practice I don't think this has a real use case for receivers, but in theory this will be allowed, yes. And it will be definitely possible with processors.

So you are right that we may need some replacement that is not always the same to avoid collisions, but is still predictable.

@mrodm
Copy link
Contributor Author

mrodm commented Sep 5, 2025

/test

Comment on lines +306 to +312
processors:
batch/11c35ad0-4351-49d4-9c78-fa679ce9d950:
send_batch_size: 10
timeout: 1s
batch/e6e379c5-6446-4090-af10-a9e5f8fc4640:
send_batch_size: 10000
timeout: 10s
Copy link
Contributor Author

Choose a reason for hiding this comment

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

With the current implementation, this could fail in some test executions:

--- FAIL: TestComparePolicies (0.00s) --- FAIL: TestComparePolicies/otel_ids (0.00s) policy_test.go:472:	Error Trace:	/home/mariorodriguez/Coding/work/elastic-package-otel/internal/testrunner/runners/policy/policy_test.go:472	Error:	Should be empty, but was --- want	+++ got	@@ -17,4 +17,4 @@ batch/componentid:	- send_batch_size: 10	- timeout: 1s	+ send_batch_size: 10000	+ timeout: 10s receivers:	Test:	TestComparePolicies/otel_ids FAIL FAIL	github.com/elastic/elastic-package/internal/testrunner/runners/policy	0.061s FAIL 

Working to replace the OTEL ids (directly on the []byte variable) before running the cleanup process.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hopefully, this is solved by replacing the OTEL IDs before cleaning up the policy with the current filters. This was added in 50de2aa

@mrodm
Copy link
Contributor Author

mrodm commented Sep 8, 2025

/test

@mrodm mrodm marked this pull request as ready for review September 8, 2025 17:48
@mrodm mrodm requested a review from jsoriano September 8, 2025 17:48
Copy link
Member

@jsoriano jsoriano left a comment

Choose a reason for hiding this comment

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

Looks good overall, added some suggestions. In any case we will need to make changes here as the E2E implementation consolidates, so we will have opportunities to revisit this.

- httpcheck/4bae34b3-8f66-49c1-b04f-d58af1b5f743
processors:
- batch/11c35ad0-4351-49d4-9c78-fa679ce9d950
- batch/e6e379c5-6446-4090-af10-a9e5f8fc4640
Copy link
Member

Choose a reason for hiding this comment

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

This is likely going to change as more plumbing is needed, see elastic/kibana#233090.

But we can go on with this change and regenerate files later.

Comment on lines 222 to 242
policy = otelComponentIDsRegexp.ReplaceAllFunc(policy, func(match []byte) []byte {
count := 0
lines := bytes.Split(match, []byte("\n"))
for i, line := range lines {
line = bytes.TrimRight(line, "\r\n")
stringLine := string(line)
if strings.Contains(stringLine, ":") {
if uniqueOtelComponentIDReplace.regexp.MatchString(stringLine) {
replacement := fmt.Sprintf(uniqueOtelComponentIDReplace.replace, strconv.Itoa(count))
count++
lines[i] = []byte(uniqueOtelComponentIDReplace.regexp.ReplaceAllString(stringLine, replacement))

// store the otel ID replaced without the space indentation and the colon to be replaced later
// (e.g. http_check/4391d954-1ffe-4014-a256-5eda78a71828 replaced by http_check/componentid-0)
otelID := strings.SplitN(strings.TrimSpace(stringLine), ":", 2)[0]
replacementsDone[otelID] = strings.SplitN(strings.TrimSpace(string(lines[i])), ":", 2)[0]
}
}
}
return bytes.Join(lines, []byte("\n"))
})
Copy link
Member

Choose a reason for hiding this comment

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

Is it neccesary to take into account the root level? Couldn't we directly replace the matching ids?

Suggested change
policy = otelComponentIDsRegexp.ReplaceAllFunc(policy, func(match []byte) []byte {
count := 0
lines := bytes.Split(match, []byte("\n"))
for i, line := range lines {
line = bytes.TrimRight(line, "\r\n")
stringLine := string(line)
if strings.Contains(stringLine, ":") {
if uniqueOtelComponentIDReplace.regexp.MatchString(stringLine) {
replacement := fmt.Sprintf(uniqueOtelComponentIDReplace.replace, strconv.Itoa(count))
count++
lines[i] = []byte(uniqueOtelComponentIDReplace.regexp.ReplaceAllString(stringLine, replacement))
// store the otel ID replaced without the space indentation and the colon to be replaced later
// (e.g. http_check/4391d954-1ffe-4014-a256-5eda78a71828 replaced by http_check/componentid-0)
otelID := strings.SplitN(strings.TrimSpace(stringLine), ":", 2)[0]
replacementsDone[otelID] = strings.SplitN(strings.TrimSpace(string(lines[i])), ":", 2)[0]
}
}
}
return bytes.Join(lines, []byte("\n"))
})
policy = uniqueOtelComponentIDReplace.regexp.ReplaceAllStringFunc(policy, func(match string) string {
replacement := fmt.Sprintf(uniqueOtelComponentIDReplace.replace, strconv.Itoa(count))
replaced := uniqueOtelComponentIDReplace.regexp.ReplaceAllString(match, replacement)
otelID, _, _ := strings.Cut(strings.TrimSpace(match), ":")
replacementsDone[otelID], _, _ = strings.Cut(strings.TrimSpace(string(replaced)), ":")
})
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe it could be done like that, but it could not be ensured that all the replacements performed would be related to OTEL.

The current implementation, at least, looks for OTEL IDs just in the block definitions detailed by the regexp otelComponentIDsRegexp:

var otelComponentIDsRegexp = regexp.MustCompile(`(?m)^(?:extensions|receivers|processors|connectors|exporters):(?:\s\{\}\n|\n(?:\s{2,}.+\n)+)`)

I'd prefer to keep it for now like this to avoid replacing unexpected strings in other settings/fields while validating these policies.

@mrodm
Copy link
Contributor Author

mrodm commented Sep 9, 2025

test integrations

@elastic-vault-github-plugin-prod

Created or updated PR in integrations repository to test this version. Check elastic/integrations#15254

Copy link
Member

@jsoriano jsoriano left a comment

Choose a reason for hiding this comment

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

👍

Co-authored-by: Jaime Soriano Pastor <jaime.soriano@elastic.co>
@elasticmachine
Copy link
Collaborator

💚 Build Succeeded

History

cc @mrodm

@mrodm mrodm merged commit ffa80e9 into elastic:main Sep 9, 2025
3 checks passed
@mrodm mrodm deleted the support-policy-tests-otel-input branch September 9, 2025 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants