Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Receiver resource filtering with CEL #948

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

bigkevmcd
Copy link
Contributor

@bigkevmcd bigkevmcd commented Oct 10, 2024

This implementation allows filtering of wildcarded resources for receivers using CEL expressions.

Closes: #491

Spec: #491 (comment)

@bigkevmcd
Copy link
Contributor Author

bigkevmcd commented Oct 10, 2024

@stefanprodan @matheuscscp I reworked it to filter the resources using CEL.

I'm not quite sure that this is really that valuable, I suspect label filtering is also more efficient?

There's some optimisation of the CEL that could be done within requestReconciliation to reduce the creation of CEL values and I can do that but I thought I'd get this out for comment.

@bigkevmcd bigkevmcd force-pushed the cel-resource-filtering branch from 4969c46 to 1fe996b Compare October 10, 2024 05:40
@bigkevmcd bigkevmcd force-pushed the cel-resource-filtering branch 3 times, most recently from d87dbfd to b1c4e7e Compare October 10, 2024 19:03
@stefanprodan stefanprodan changed the title CEL Resource Filtering Implement Receiver resource filtering with CEL Oct 11, 2024
@bigkevmcd bigkevmcd force-pushed the cel-resource-filtering branch from 45bd724 to 1e6929c Compare October 13, 2024 14:57
@bigkevmcd bigkevmcd marked this pull request as ready for review October 13, 2024 15:18
@bigkevmcd bigkevmcd marked this pull request as draft October 16, 2024 07:30
@bigkevmcd bigkevmcd force-pushed the cel-resource-filtering branch from 1e6929c to d658d4a Compare October 17, 2024 08:46
@bigkevmcd bigkevmcd marked this pull request as ready for review October 17, 2024 08:54
Copy link
Member

@matheuscscp matheuscscp left a comment

Choose a reason for hiding this comment

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

Thanks again for all the work here, @bigkevmcd! I'm very excited for this feature 😄

This is just a preliminary review. I will try to review this again soon.

internal/server/receiver_handlers.go Show resolved Hide resolved
@bigkevmcd bigkevmcd force-pushed the cel-resource-filtering branch 4 times, most recently from 5a22c4f to bddfd56 Compare October 18, 2024 13:06
Copy link
Member

@stefanprodan stefanprodan left a comment

Choose a reason for hiding this comment

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

LGTM

Thanks @bigkevmcd 🥇

Copy link
Member

@matheuscscp matheuscscp left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks @bigkevmcd! Pretty cool contribution 👍

internal/server/cel.go Show resolved Hide resolved
internal/server/receiver_handlers.go Outdated Show resolved Hide resolved
api/v1/receiver_types.go Show resolved Hide resolved
@bigkevmcd bigkevmcd force-pushed the cel-resource-filtering branch 6 times, most recently from 8e892ef to 18c1f31 Compare November 1, 2024 14:34
@stefanprodan
Copy link
Member

@bigkevmcd this is good to go, please signoff all your commits and force push.

@bigkevmcd bigkevmcd force-pushed the cel-resource-filtering branch from 8a9e435 to 57c36b0 Compare November 1, 2024 20:58
@bigkevmcd
Copy link
Contributor Author

@pjbgf

+1 on leaning on k8s' default limits as a starting point. It might be worth just confirming whether the payload and expression sizes for this use case are equivalent, so that those limits would not be too forgiving.

https://github.com/kubernetes/kubernetes/blob/cf480a3a1a9cb22f3439c0a7922822d9f67f31b5/staging/src/k8s.io/apiserver/pkg/apis/cel/config.go#L40

That's 3MiB, I've definitely seen GitHub hook notifications that were > 1.5MiB.

CEL for Receiver notification filtering

This introduces CEL for filtering CEL resources in a Receiver.

Users can define a CEL expression that is applied as a filter for
resources that are identified for notification.

A CEL expression that returns false means that a resource will not be
annotated.

Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
This moves the JSON body to request.body from request to allow for
future expansion with the headers.

Add documentation for the CEL functionality to the receivers doc.

Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
Refactor to reduce duplication.

Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
If the .spec.resourceFilter is provided, and can't be parsed by the CEL
environment, the resource will not be ready, and an appropriate error
indicated.

Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
In the event of a CEL expresion error, this doesn't return the error to
the controller-runtime reconciler mechanism.

This means that the reconciliation will not be retried until there's a
change to the resource.

Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
* Don't pass log through - get it from the context
* Use ContextEval - need to set a timeout on the context that's passed

Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
This adds more testing for the CEL evaluation mechanism for resource
filtering.

Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
@bigkevmcd bigkevmcd force-pushed the cel-resource-filtering branch from f79599e to e438ca1 Compare January 28, 2025 13:45
@matheuscscp matheuscscp self-requested a review January 28, 2025 17:12
Copy link
Member

@matheuscscp matheuscscp left a comment

Choose a reason for hiding this comment

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

New batch of comments ❤️

@@ -67,6 +67,11 @@ type ReceiverSpec struct {
// +required
Resources []CrossNamespaceObjectReference `json:"resources"`

// ResourceFilter is a CEL expression that is applied to each Resource
// referenced in the Resources. If the expression returns false then the
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// referenced in the Resources. If the expression returns false then the
// referenced in the Resources field. If the expression returns false then the

api/v1/receiver_types.go Outdated Show resolved Hide resolved

To filter the resources that are reconciled you can use [Common Expression Language (CEL)](https://cel.dev/).

For example to trigger `ImageRepositories` on notifications from [Google Artifact Registry](https://cloud.google.com/artifact-registry/docs/configure-notifications#examples) you can define a receiver.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
For example to trigger `ImageRepositories` on notifications from [Google Artifact Registry](https://cloud.google.com/artifact-registry/docs/configure-notifications#examples) you can define a receiver.
For example, to trigger `ImageRepositories` on notifications from [Google Artifact Registry](https://cloud.google.com/artifact-registry/docs/configure-notifications#examples) you can define the following receiver:

docs/spec/v1/receivers.md Outdated Show resolved Hide resolved
api/v1/condition_types.go Show resolved Hide resolved
Copy link
Member

@matheuscscp matheuscscp left a comment

Choose a reason for hiding this comment

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

Still need to go over internal/server/receiver_handlers.go once again

Comment on lines 770 to 813
There are a number of functions available to the CEL expressions beyond the basic CEL functionality.

The [Strings extension](https://github.com/google/cel-go/tree/master/ext#strings) is available.

In addition the notifications-controller CEL implementation provides the following functions:

#### first

Returns the first element of a CEL array expression.

```
<list<any>>.first() -> <any>
```

This is syntactic sugar for `['hello', 'mellow'][0]`

Examples:

```
['hello', 'mellow'].first() // returns 'hello'
[].first() // returns nil
'this/test'.split('/').first() // returns 'this'
```

#### last

Returns the last element of a CEL array expression.

```
<list<any>>.last() -> <any>
```

Examples:

```
['hello', 'mellow'].last() // returns 'mellow'
[].last() // returns nil
'this/test'.split('/').last() // returns 'test'
```

This is syntactic sugar for `['hello', 'mellow'][size(['hello, 'mellow'])-1]`

For zero-length array values, these will both return `nil`.

Copy link
Member

Choose a reason for hiding this comment

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

I think we can remove all of this since now these functions are in the upstream CEL library.

if filter := obj.Spec.ResourceFilter; filter != "" {
err := server.ValidateCELExpression(filter)
if err != nil {
conditions.MarkFalse(obj, meta.ReadyCondition, apiv1.InvalidCELExpressionReason, "%s", err)
Copy link
Member

Choose a reason for hiding this comment

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

+1 on this

internal/server/cel.go Outdated Show resolved Hide resolved
internal/controller/receiver_controller.go Show resolved Hide resolved
// ValidateCELEXpression accepts a CEL expression and will parse and check that
// it's valid, if it's not valid an error is returned.
func ValidateCELExpression(s string) error {
_, err := newCELProgram(s)
Copy link
Member

Choose a reason for hiding this comment

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

Let's use the library as discussed (still needs to be merged/released, will happen soon):

fluxcd/pkg#858

@@ -0,0 +1,194 @@
/*
Copy link
Member

Choose a reason for hiding this comment

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

Most of this file can be removed in favor of fluxcd/pkg#858

@@ -0,0 +1,131 @@
package server
Copy link
Member

@matheuscscp matheuscscp Jan 29, 2025

Choose a reason for hiding this comment

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

This test file can be removed in favor of fluxcd/pkg#858

@matheuscscp
Copy link
Member

matheuscscp commented Jan 31, 2025

@bigkevmcd we have released the fluxcd/pkg packages, please pull them in with:

  • go get github.com/fluxcd/pkg/apis/meta@v1.10.0 for InvalidCELExpressionReason
  • go get github.com/fluxcd/pkg/runtime@v0.53.0 for the runtime/cel library

🙏

Edit: Like Stefan said below, just need to rebase.

@stefanprodan
Copy link
Member

@bigkevmcd if you rebase with main, you'll find runtime/cel and the InvalidCELExpressionReason.

Co-authored-by: Matheus Pimenta <matheuscscp@gmail.com>
Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
Co-authored-by: Matheus Pimenta <matheuscscp@gmail.com>
Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>

Strip out unnecessary documentation.
@bigkevmcd bigkevmcd force-pushed the cel-resource-filtering branch from 7183c3c to fc59218 Compare February 3, 2025 19:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/api API related issues and pull requests area/receiver Webhook receiver related issues and PRs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Filtering for incoming webhooks
5 participants