Skip to content

eventchecker: support generic map types#4763

Open
AritraDey-Dev wants to merge 5 commits into
cilium:mainfrom
AritraDey-Dev:pr/aritra/eventchecker-generic-map-support
Open

eventchecker: support generic map types#4763
AritraDey-Dev wants to merge 5 commits into
cilium:mainfrom
AritraDey-Dev:pr/aritra/eventchecker-generic-map-support

Conversation

@AritraDey-Dev
Copy link
Copy Markdown
Member

@AritraDey-Dev AritraDey-Dev commented Mar 14, 2026

Description

This PR extends the eventchecker to support generic map fields. Previously,PR #260 hardcoded support only for map[string]string.

This PR introduces a generic MapMatcher to automatically handle different key-value types (like int and bool).

Note: MapMatcher is made generic so future proto map fields with non-string value types (e.g. map<string, uint32>) are automatically supported by codegen without additional matcher changes.

Changelog

eventchecker: support generic map types

@AritraDey-Dev AritraDey-Dev requested a review from a team as a code owner March 14, 2026 07:47
@AritraDey-Dev AritraDey-Dev force-pushed the pr/aritra/eventchecker-generic-map-support branch 2 times, most recently from a46d958 to 40f6d5e Compare March 14, 2026 08:20
@andrewstrohman andrewstrohman added the release-note/minor This PR introduces a minor user-visible change label Mar 20, 2026
@andrewstrohman
Copy link
Copy Markdown
Contributor

This is note for myself:

I was able to generate the last commit in this series by executing:
BUF_BREAKING_AGAINST_BRANCH=AritraDey-Dev/pr/aritra/eventchecker-generic-map-support make codegen && make vendor

There is a comment in the Makefile for the protogen target:

 # Need to call vendor twice here, once before and once after codegen the reason
 # being we need to grab changes first plus pull in whatever gets generated here.

The code originally did this when this comment was introduced, and has since changed to not do this.

Comment on lines -73 to +74
checkerVar := fmt.Sprintf("%s.%s", checkerVarName, field.GoName)
eventVar := fmt.Sprintf("%s.%s", eventVarName, field.GoName)
checkerVar := checkerVarName + "." + field.GoName
eventVar := eventVarName + "." + field.GoName
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There are a lot of changes in this commit like this, where we change Sprintf() calls to string concatenation ("+"). It doesn't seem like the motivation to do this is related to what is described in the commit message. Should these changes be moved out into a separate commit?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes moved this to a separate commit,thanks.

Comment on lines +876 to +890
// For Pod_Labels specifically
if field.GoIdent.GoName == "Pod_Labels" {
smatcher := common.StringMatcherIdent(g, "Full")
return `{
checkerVar := make(` + mident + `)
splitN := strings.SplitN
for _, s := range event.PodLabels {
kv := splitN(s, "=", 2)
if len(kv) == 2 {
checkerVar[kv[0]] = *` + smatcher + `(kv[1])
}
}
checker.PodLabels = checkerVar
}`, nil
}
Copy link
Copy Markdown
Contributor

@andrewstrohman andrewstrohman Mar 23, 2026

Choose a reason for hiding this comment

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

I don't see this in the generated output. Why is this code not currently used?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Great catch! It's dead code left over from earlier iterations,the struct field is actually named PodLabels (so "Pod_Labels" never matches) and new generic map logic handles the native map perfectly, so I'll just remove it.

@@ -0,0 +1,109 @@
// SPDX-License-Identifier: Apache-2.0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It would probably be better if this was in a different commit; one commit for your changes and another for the result of "make vendor".

I do it this way because I find it easier to rebase / cherry-pick. This way, I don't have to handle conflicts for the generated files. Instead, I just run "make vendor" to regenerate the commit that corresponds to the original "make vendor" commit.

Comment on lines +12 to +15
// Matcher is a generic interface for matching values of type T.
type Matcher[T any] interface {
Match(T) error
}
Copy link
Copy Markdown
Contributor

@andrewstrohman andrewstrohman Mar 23, 2026

Choose a reason for hiding this comment

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

I see that this type is never used. I think you created this for clarity and/or documentation purposes, which makes sense to me. I just want to confirm that this is intentional, and not something left over from an earlier approach.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

You're spot on! Matcher[T] is indeed currently unused as a formal type constraint,it's mostly there for docs to show the expected shape of the matchers that go into MapMatcher.
The main reason I used any for M in MapMatcher[K, V, M] instead of the Matcher interface is to give us max flexibility. Specifically, it lets this work seamlessly with existing matchers (like StringMatcher) that have pointer receivers, without us having to tweak their source files at all. Since the Match method dynamically checks both the value and its pointer during execution, having the formal interface constraint wasn't strictly required to get the job done.

return nil
}

func TestMapMatcher(t *testing.T) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this test also test UnmarshalJSON ( viayaml.Unmarshal), like how is done in TestPrimitiveMatcher?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I didn't add a specific unmarshal test for MapMatcher because its UnmarshalJSON method is just standard boilerplate mapping (using the common Alias type trick to prevent infinite recursion).
It has no custom branching or fallback logic to verify. PrimitiveMatcher, on the other hand, absolutely needed a specific test because it has handwritten, custom fallback logic to handle two completely different YAML formats (parsing both shorthand bare values and full structs).

@andrewstrohman
Copy link
Copy Markdown
Contributor

I see the benefit of making more generic code that can be re-used. I also like how the From method is implemented for maps, in case we want to use that in the future.

That being said, I'm wondering if there any other motivation that I'm not aware of. Do you plan to use this for another change in the future? If so, please add that information to the PR, so that reviewers can better understand where you are headed.

Copy link
Copy Markdown
Contributor

@andrewstrohman andrewstrohman left a comment

Choose a reason for hiding this comment

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

I left some comments, but overall LGTM.

That being said, all this code and concepts were new to me as I had never looked at the protoc-gen-go-tetragon part of the codebase before reviewing this. So, it would be great if we could get another review from someone with more background/expertise in this this area before merging.

@AritraDey-Dev AritraDey-Dev force-pushed the pr/aritra/eventchecker-generic-map-support branch from 40f6d5e to 3dc6558 Compare April 4, 2026 17:34
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 4, 2026

Deploy Preview for tetragon ready!

Name Link
🔨 Latest commit 3dc6558
🔍 Latest deploy log https://app.netlify.com/projects/tetragon/deploys/69d14ba8fce4e50008d17d3d
😎 Deploy Preview https://deploy-preview-4763--tetragon.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

This commit adds a new MapMatcher that works with different generic map types.
This removes the hardcoded limitation of only checking string-to-string
maps. A PrimitiveMatcher is also included to compare simple values like
numbers or booleans inside maps.

Signed-off-by: Aritra Dey <adey01027@gmail.com>
@AritraDey-Dev AritraDey-Dev force-pushed the pr/aritra/eventchecker-generic-map-support branch from 3dc6558 to 4c7857b Compare April 4, 2026 18:10
Update the api/vendor directory to include the newly added generic
MapMatcher and PrimitiveMatcher. This is required for the eventchecker
code generation to correctly reference these matchers in the API.

Signed-off-by: Aritra Dey <adey01027@gmail.com>
@AritraDey-Dev AritraDey-Dev force-pushed the pr/aritra/eventchecker-generic-map-support branch from 4c7857b to 4c70e12 Compare April 4, 2026 18:27
@AritraDey-Dev AritraDey-Dev force-pushed the pr/aritra/eventchecker-generic-map-support branch 2 times, most recently from 84bbee1 to 83e3350 Compare April 11, 2026 21:29
Replace fmt.Sprintf with standard string concatenation when generating
field and event names. This addresses perfsprint linter warnings
about simple string formatting.

Signed-off-by: Aritra Dey <adey01027@gmail.com>
This commit updates the codegen tool to handle map types beyond strings.
The tool now automatically creates matchers for maps with different key
and value types. It also adds the required logic to extract these map
values from events.

Signed-off-by: Aritra Dey <adey01027@gmail.com>
Regenerate the eventchecker code using the updated codegen tool.
This includes the new generic map matchers in the API.

Signed-off-by: Aritra Dey <adey01027@gmail.com>
@AritraDey-Dev AritraDey-Dev force-pushed the pr/aritra/eventchecker-generic-map-support branch from 83e3350 to c1953c3 Compare April 11, 2026 21:33
@AritraDey-Dev
Copy link
Copy Markdown
Member Author

That being said, I'm wondering if there any other motivation that I'm not aware of. Do you plan to use this for another change in the future? If so, please add that information to the PR, so that reviewers can better understand where you are headed.

Hey, the main fix was PodLabels/PodAnnotations, but this patch made MapMatcher generic so any future proto map fields with non-string values (e.g. map<string, uint32>) just work without touching the matcher code again. Will update the PR description!

@kkourt kkourt requested a review from will-isovalent April 14, 2026 07:25
Copy link
Copy Markdown
Contributor

@will-isovalent will-isovalent left a comment

Choose a reason for hiding this comment

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

Hey, thanks so much for the contribution. The changes make sense to me.

If it's not too much effort, I think we probably also need to think about how you could express integer ranges and inequalities here in addition to raw equality checks. This could also be done as a follow-up though.

@kkourt
Copy link
Copy Markdown
Contributor

kkourt commented Apr 29, 2026

Hey, thanks so much for the contribution. The changes make sense to me.

If it's not too much effort, I think we probably also need to think about how you could express integer ranges and inequalities here in addition to raw equality checks. This could also be done as a follow-up though.

@will-isovalent do you think this should be in the context of this PR, or can it be a follow-up?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/minor This PR introduces a minor user-visible change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants