-
Notifications
You must be signed in to change notification settings - Fork 426
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
Cel interceptor #285
Cel interceptor #285
Conversation
Hi @bigkevmcd. Thanks for your PR. I'm waiting for a tektoncd member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Some thoughts I've had since the initial implementation... Instead of one expressions:
- "headers.match(...)"
- "body.pull_request.head.repo.fork == false" Where each of the expressions would need to return true, this would improve readability (over very long expressions). Also, there's no way currently to add a custom response header, this could be implemented similar to the This is related to #247 |
Also, in order to avoid the invisible coupling between the interceptor modifying the request body, and bindings, CEL could be added to the list of expression languages for bindings. |
/ok-to-test |
The following is the coverage report on pkg/.
|
/test pull-tekton-triggers-build-tests |
The following is the coverage report on pkg/.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR @bigkevmcd I started playing around with your branch the other day and overall it looks great.
The main thing that I'd like to see changed is the modification of the payload (the Value
field) -- I think its a super useful feature that we'd probably want to add but I think we should do that in a followup. For the 0.2 release, I think having just the expressions for filtering would be great!
Oh, and would you mind squashing the commits 😄 ?
@@ -67,7 +67,7 @@ func (s *EventListenerSpec) validate(ctx context.Context, el *EventListener) *ap | |||
|
|||
func (i *EventInterceptor) validate(ctx context.Context, namespace string) *apis.FieldError { | |||
// Validate at least one | |||
if i.Webhook == nil && i.Github == nil && i.Gitlab == nil { | |||
if i.Webhook == nil && i.Github == nil && i.Gitlab == nil && i.CEL == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also validate that if CEL has the expression
field set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add validation for the renamed filter
expression.
pkg/interceptors/cel/cel.go
Outdated
func (w *Interceptor) ExecuteTrigger(payload []byte, request *http.Request, _ *triggersv1.EventListenerTrigger, _ string) ([]byte, error) { | ||
env, err := makeCelEnv() | ||
if err != nil { | ||
return nil, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add some extra context when returning errors in this file?
e.g. fmt.Errof("error creating cel environment: %w, err)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
pkg/interceptors/cel/cel_test.go
Outdated
{ | ||
name: "simple header check with non matching header", | ||
CEL: &triggersv1.CELInterceptor{ | ||
Expression: "headers['X-Test'][0] == 'unknown'", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The headers
part here is slightly different from headers
in TriggerBindings
.
In Bindings, the keyword is header
not headers
-- though headers
does sound like the more correct term.
Also, you do not have to use array accessors e.g. $(headers.foo)
not $(headers.foo[0])
Its probably worth being consistent here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify, you would prefer it to emulate JSON path expressions in CEL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if CEL is the right expression language to use, maybe we could augment the JSON path expressions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, the syntax header['X-Test'][0]
is one possible option.
The header value is a https://golang.org/pkg/net/http/#Header value, but, it's translated in CEL into a map, so, there's a custom match overload, which uses .Get()
on the value, this is doing more than a simple key-value lookup.
I'm not sure how easy it is to emulate JSON path expressions in CEL without a significant amount of work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By "emulating", I was just referring to making it easy to access single valued headers i.e header['X-Test'][0] vs header['X-Test']. From reading @wlynch 's comment it seems like that might already be the case...
We definitely should not try to do anything more complicated than that 😅
Another more verbose option could be the multiple interceptor support that @wlynch is working on
This could be an interesting add on for the future...(JSONPath also supports filtering, maybe that could be a interceptor too 😛 ) |
This would be slightly different, in that it would be more about readability to avoid having to write long expressions like |
6229aed
to
33bc5b8
Compare
The following is the coverage report on pkg/.
|
The main driver for this is to get rid of an external interceptor that is doing matching, and extracting the SHA and trimming it (amongst other things). The "values" behaviour emulates this behaviour, so, I'd like to see some discussion about what alternatives could look like. |
33bc5b8
to
9d0be43
Compare
The following is the coverage report on pkg/.
|
9d0be43
to
1478ee9
Compare
The following is the coverage report on pkg/.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should make sure to add a reference to the issue (#49) in the PR body / commit message.
Otherwise looking good! :D
@@ -67,7 +67,7 @@ func (s *EventListenerSpec) validate(ctx context.Context, el *EventListener) *ap | |||
|
|||
func (i *EventInterceptor) validate(ctx context.Context, namespace string) *apis.FieldError { | |||
// Validate at least one | |||
if i.Webhook == nil && i.Github == nil && i.Gitlab == nil { | |||
if i.Webhook == nil && i.Github == nil && i.Gitlab == nil && i.CEL == nil { | |||
return apis.ErrMissingField("interceptor") | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to add logic for numSet below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's also add a test to make sure CEL and another Interceptor can't be set at the same time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this still needs to be added
return cel.Functions( | ||
&functions.Overload{ | ||
Operator: "match", | ||
Function: matchHeader}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, this function is to simplify accessing headers with only 1 value, correct? Could we just use the built-in in
function instead?
e.g. in('foo', header['myheader'])
. See https://github.com/google/cel-spec/blob/master/doc/langdef.md for more details.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not quite what it does, the value of header
is https://golang.org/pkg/net/http/#Header and the match
delegates to the Get
method, which does a bit more than accessing the header for single-value headers.
func evaluate(expr string, env cel.Env, data map[string]interface{}) (ref.Val, error) { | ||
parsed, issues := env.Parse(expr) | ||
if issues != nil && issues.Err() != nil { | ||
return nil, issues.Err() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we know what will be returned in this error message? e.g. will it be clear what exactly is failing? We may want to consider wrapping this error to make it clear what went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message from CEL is pretty good, the test I added only really tests a subset of the message.
failed to evaluate expression 'header['X-Test': ERROR: <input>:1:8: Syntax error: token recognition error at: ''X-Test'
| header['X-Test
| .......^
ERROR: <input>:1:15: Syntax error: mismatched input '<EOF>' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER}
| header['X-Test
| ..............^
|
1478ee9
to
ee729b1
Compare
The following is the coverage report on pkg/.
|
The following is the coverage report on pkg/.
|
e841acb
to
5a0182f
Compare
The following is the coverage report on pkg/.
|
5a0182f
to
45ec5b9
Compare
The following is the coverage report on pkg/.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey @bigkevmcd , sorry about the long review time. This is looking almost good to go - just needs a rebase, and a couple of minor issues.
One thing is that this is going to conflict with #272 depending on which gets in first
docs/eventlisteners.md
Outdated
[CEL](https://github.com/google/cel-go) expression language. | ||
|
||
Supported features include case-insensitive matching on request headers, and the | ||
ability to add new keys (which can be extracted in a TemplateBinding) to the response |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we decided to remove the part about adding new keys for now
@@ -67,7 +67,7 @@ func (s *EventListenerSpec) validate(ctx context.Context, el *EventListener) *ap | |||
|
|||
func (i *EventInterceptor) validate(ctx context.Context, namespace string) *apis.FieldError { | |||
// Validate at least one | |||
if i.Webhook == nil && i.Github == nil && i.Gitlab == nil { | |||
if i.Webhook == nil && i.Github == nil && i.Gitlab == nil && i.CEL == nil { | |||
return apis.ErrMissingField("interceptor") | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this still needs to be added
Looks like we need to add this as well! |
45ec5b9
to
34980e8
Compare
The following is the coverage report on pkg/.
|
70975dc
to
08a2057
Compare
The following is the coverage report on pkg/.
|
The following is the coverage report on pkg/.
|
08a2057
to
aa10c18
Compare
The following is the coverage report on pkg/.
|
CEL interceptors parse expressions to filter requests based on JSON bodies and request headers, using the | ||
[CEL](https://github.com/google/cel-go) expression language. | ||
|
||
Supported features include case-insensitive matching on request headers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's document the custom methods we add similar to https://github.com/google/cel-spec/blob/master/doc/langdef.md#list-of-standard-definitions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! 😄 Thanks!
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: dibyom, wlynch The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
aa10c18
to
c5662b2
Compare
The following is the coverage report on pkg/.
|
This adds a cel interceptor, that uses a a CEL expression to filter request bodies. This implements issue tektoncd#49.
b5fd2e6
to
5d03795
Compare
The following is the coverage report on pkg/.
|
The following is the coverage report on pkg/.
|
/lgtm |
Changes
This implements a CEL based interceptor that allows matching on request bodies, and request headers.
Submitter Checklist
These are the criteria that every PR should meet, please check them off as you
review them:
See the contribution guide for more details.
Release Notes