Skip to content

Commit 1e6929c

Browse files
committed
Add request.body in CEL notification filtering
This moves the JSON body to request.body from request to allow for future expansion with the headers. Add documentation Signed-off-by: Kevin McDermott <[email protected]>
1 parent b1c4e7e commit 1e6929c

File tree

3 files changed

+54
-4
lines changed

3 files changed

+54
-4
lines changed

docs/spec/v1/receivers.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,55 @@ resources:
700700
**Note:** Cross-namespace references [can be disabled for security
701701
reasons](#disabling-cross-namespace-selectors).
702702

703+
#### Filtering reconciled objects with CEL
704+
705+
To filter the resources that are reconciled you can use [Common Expression Language (CEL)](https://cel.dev/).
706+
707+
For example to trigger `ImageRepositories` on notifications from [Google Artifact Regisry](https://cloud.google.com/artifact-registry/docs/configure-notifications#examples) you can define a receiver.
708+
709+
```yaml
710+
apiVersion: notification.toolkit.fluxcd.io/v1
711+
kind: Receiver
712+
metadata:
713+
name: gar-receiver
714+
namespace: apps
715+
spec:
716+
type: gcr
717+
secretRef:
718+
name: flux-gar-token
719+
resources:
720+
- apiVersion: image.toolkit.fluxcd.io/v1beta2
721+
kind: ImageRepository
722+
name: "*"
723+
matchLabels:
724+
registry: gar
725+
```
726+
727+
This will trigger the reconciliation of all `ImageRepositories` with matching labels `registry: gar`, but if you want to only notify `ImageRepository` resources that are referenced from the incoming hook you can use CEL to filter the resources.
728+
729+
```yaml
730+
apiVersion: notification.toolkit.fluxcd.io/v1
731+
kind: Receiver
732+
metadata:
733+
name: gar-receiver
734+
namespace: apps
735+
spec:
736+
type: gcr
737+
secretRef:
738+
name: flux-gar-token
739+
resources:
740+
- apiVersion: image.toolkit.fluxcd.io/v1beta2
741+
kind: ImageRepository
742+
name: "*"
743+
matchLabels:
744+
registry: gar
745+
resourceFilter: 'request.tag.contains(resource.metadata.name)'
746+
```
747+
748+
To reduce the number of `ImageRepositories` that are reconciled, you can filter them with a CEL expression.
749+
750+
```
751+
703752
### Secret reference
704753

705754
`.spec.secretRef.name` is a required field to specify a name reference to a

internal/server/cel.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ func newCELEvaluator(expr string, req *http.Request) (resourcePredicate, error)
5353

5454
out, _, err := prg.Eval(map[string]any{
5555
"resource": data,
56-
"request": body,
56+
"request": map[string]any{
57+
"body": body,
58+
},
5759
})
5860
if err != nil {
5961
return nil, fmt.Errorf("expression %v failed to evaluate: %w", expr, err)
@@ -74,7 +76,6 @@ func makeCELEnv() (*cel.Env, error) {
7476
mapStrDyn := decls.NewMapType(decls.String, decls.Dyn)
7577
return cel.NewEnv(
7678
celext.Strings(),
77-
celext.Encoders(),
7879
notifications(),
7980
cel.Declarations(
8081
decls.NewVar("resource", mapStrDyn),

internal/server/receiver_handler_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ func Test_handlePayload(t *testing.T) {
789789
},
790790
},
791791
},
792-
ResourceFilter: `has(resource.metadata.annotations) && request.tag.split('/').last().split(":").first() == resource.metadata.annotations['update-image']`,
792+
ResourceFilter: `has(resource.metadata.annotations) && request.body.tag.split('/').last().split(":").first() == resource.metadata.annotations['update-image']`,
793793
},
794794
Status: apiv1.ReceiverStatus{
795795
WebhookPath: apiv1.ReceiverWebhookPath,
@@ -878,7 +878,7 @@ func Test_handlePayload(t *testing.T) {
878878
Name: "test-resource",
879879
},
880880
},
881-
ResourceFilter: `has(resource.metadata.annotations) && request.tag.split('/').last().split(":").first() == resource.metadata.annotations['update-image']`,
881+
ResourceFilter: `has(resource.metadata.annotations) && request.body.tag.split('/').last().split(":").first() == resource.metadata.annotations['update-image']`,
882882
},
883883
Status: apiv1.ReceiverStatus{
884884
WebhookPath: apiv1.ReceiverWebhookPath,

0 commit comments

Comments
 (0)