diff --git a/cmd/binding-eval/cmd/root.go b/cmd/binding-eval/cmd/root.go index 92c87559e..8c38fa88e 100644 --- a/cmd/binding-eval/cmd/root.go +++ b/cmd/binding-eval/cmd/root.go @@ -80,7 +80,7 @@ func evalBinding(w io.Writer, bindingPath, httpPath string) error { BindingParams: bindingParams, } - params, err := template.ResolveParams(t, body, r.Header, map[string]interface{}{}) + params, err := template.ResolveParams(t, body, r.Header, map[string]interface{}{}, template.NewTriggerContext("")) if err != nil { return fmt.Errorf("error resolving params: %w", err) } diff --git a/cmd/triggerrun/cmd/root.go b/cmd/triggerrun/cmd/root.go index 00fc1d9de..9f8d34ce3 100644 --- a/cmd/triggerrun/cmd/root.go +++ b/cmd/triggerrun/cmd/root.go @@ -230,7 +230,7 @@ func processTriggerSpec(kubeClient kubernetes.Interface, client triggersclientse if iresp != nil && iresp.Extensions != nil { extensions = iresp.Extensions } - params, err := template.ResolveParams(rt, finalPayload, header, extensions) + params, err := template.ResolveParams(rt, finalPayload, header, extensions, template.NewTriggerContext(eventID)) if err != nil { log.Error("Failed to resolve parameters", err) return nil, err diff --git a/docs/triggerbindings.md b/docs/triggerbindings.md index 05a3ad746..a3e6b44a6 100644 --- a/docs/triggerbindings.md +++ b/docs/triggerbindings.md @@ -185,6 +185,17 @@ spec: ref: git-clone-template ``` +## Accessing EventListener Event Context + +The EventListener has a set of internal data points that are maintained for the complete processing +of a single event. These values are available for use in `TriggerBinding` objects. + +This data can be accessed on the `context` parameter, as an example: + +```shell +$(context.eventID) # access the internal eventID of the request +``` + ## Accessing JSON keys containing periods (`.`) To access a JSON key that contains a period (`.`), you must escape the period with a backslash (`\.`). For example: diff --git a/pkg/sink/sink.go b/pkg/sink/sink.go index 4fb9264d0..ecae99869 100644 --- a/pkg/sink/sink.go +++ b/pkg/sink/sink.go @@ -400,7 +400,7 @@ func (r Sink) processTrigger(t triggersv1.Trigger, el *triggersv1.EventListener, if iresp != nil && iresp.Extensions != nil { extensions = iresp.Extensions } - params, err := template.ResolveParams(rt, finalPayload, header, extensions) + params, err := template.ResolveParams(rt, finalPayload, header, extensions, template.NewTriggerContext(eventID)) if err != nil { log.Error(err) return diff --git a/pkg/template/event.go b/pkg/template/event.go index c013717d8..8ad548d81 100644 --- a/pkg/template/event.go +++ b/pkg/template/event.go @@ -36,15 +36,23 @@ const ( OldEscapeAnnotation = "triggers.tekton.dev/old-escape-quotes" ) +type TriggerContext struct { + EventID string `json:"eventID"` +} + +func NewTriggerContext(eventID string) TriggerContext { + return TriggerContext{EventID: eventID} +} + // ResolveParams takes given triggerbindings and produces the resulting // resource params. -func ResolveParams(rt ResolvedTrigger, body []byte, header http.Header, extensions map[string]interface{}) ([]triggersv1.Param, error) { +func ResolveParams(rt ResolvedTrigger, body []byte, header http.Header, extensions map[string]interface{}, triggerContext TriggerContext) ([]triggersv1.Param, error) { var ttParams []triggersv1.ParamSpec if rt.TriggerTemplate != nil { ttParams = rt.TriggerTemplate.Spec.Params } - out, err := applyEventValuesToParams(rt.BindingParams, body, header, extensions, ttParams) + out, err := applyEventValuesToParams(rt.BindingParams, body, header, extensions, ttParams, triggerContext) if err != nil { return nil, fmt.Errorf("failed to ApplyEventValuesToParams: %w", err) } @@ -71,10 +79,11 @@ type event struct { Header map[string]string `json:"header"` Body interface{} `json:"body"` Extensions map[string]interface{} `json:"extensions"` + Context TriggerContext `json:"context"` } // newEvent returns a new Event from HTTP headers and body -func newEvent(body []byte, headers http.Header, extensions map[string]interface{}) (*event, error) { +func newEvent(body []byte, headers http.Header, extensions map[string]interface{}, triggerContext TriggerContext) (*event, error) { var data interface{} if len(body) > 0 { if err := json.Unmarshal(body, &data); err != nil { @@ -90,14 +99,16 @@ func newEvent(body []byte, headers http.Header, extensions map[string]interface{ Header: joinedHeaders, Body: data, Extensions: extensions, + Context: triggerContext, }, nil } // applyEventValuesToParams returns a slice of Params with the JSONPath variables replaced // with values from the event body, headers, and extensions. func applyEventValuesToParams(params []triggersv1.Param, body []byte, header http.Header, extensions map[string]interface{}, - defaults []triggersv1.ParamSpec) ([]triggersv1.Param, error) { - event, err := newEvent(body, header, extensions) + defaults []triggersv1.ParamSpec, + triggerContext TriggerContext) ([]triggersv1.Param, error) { + event, err := newEvent(body, header, extensions, triggerContext) if err != nil { return nil, fmt.Errorf("failed to marshal event: %w", err) } diff --git a/pkg/template/event_test.go b/pkg/template/event_test.go index 39f895edd..68ebf061b 100644 --- a/pkg/template/event_test.go +++ b/pkg/template/event_test.go @@ -47,6 +47,9 @@ func toString(rawMessages []json.RawMessage) []string { } func TestApplyEventValuesMergeInDefaultParams(t *testing.T) { + context := TriggerContext{ + EventID: "1234567", + } var ( oneDefault = "onedefault" twoDefault = "twodefault" @@ -127,7 +130,7 @@ func TestApplyEventValuesMergeInDefaultParams(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := applyEventValuesToParams(tt.args.params, nil, nil, nil, tt.args.paramSpecs) + got, err := applyEventValuesToParams(tt.args.params, nil, nil, nil, tt.args.paramSpecs, context) if err != nil { t.Errorf("applyEventValuesToParams(): unexpected error: %s", err.Error()) } @@ -141,6 +144,9 @@ func TestApplyEventValuesMergeInDefaultParams(t *testing.T) { func TestApplyEventValuesToParams(t *testing.T) { var objects = `{"a":"v","c":{"d":"e"},"empty": "","null": null, "number": 42}` var arrays = `[{"a": "b"}, {"c": "d"}, {"e": "f"}]` + context := TriggerContext{ + EventID: "1234567", + } tests := []struct { name string params []triggersv1.Param @@ -300,7 +306,7 @@ func TestApplyEventValuesToParams(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := applyEventValuesToParams(tt.params, tt.body, tt.header, tt.extensions, nil) + got, err := applyEventValuesToParams(tt.params, tt.body, tt.header, tt.extensions, nil, context) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -312,6 +318,9 @@ func TestApplyEventValuesToParams(t *testing.T) { } func TestApplyEventValuesToParams_Error(t *testing.T) { + context := TriggerContext{ + EventID: "1234567", + } tests := []struct { name string params []triggersv1.Param @@ -341,7 +350,7 @@ func TestApplyEventValuesToParams_Error(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := applyEventValuesToParams(tt.params, tt.body, tt.header, tt.extensions, nil) + got, err := applyEventValuesToParams(tt.params, tt.body, tt.header, tt.extensions, nil, context) if err == nil { t.Errorf("did not get expected error - got: %v", got) } @@ -350,6 +359,8 @@ func TestApplyEventValuesToParams_Error(t *testing.T) { } func TestResolveParams(t *testing.T) { + eventID := "1234567" + tests := []struct { name string bindingParams []triggersv1.Param @@ -450,10 +461,12 @@ func TestResolveParams(t *testing.T) { bindingParams: []triggersv1.Param{ {Name: "param1", Value: "qux"}, {Name: "param2", Value: "$(body.foo)"}, + {Name: "event1", Value: "$(context.eventID)"}, }, want: []triggersv1.Param{ {Name: "param1", Value: "qux"}, {Name: "param2", Value: "bar\\r\\nbaz"}, + {Name: "event1", Value: "1234567"}, }, }} @@ -463,7 +476,8 @@ func TestResolveParams(t *testing.T) { BindingParams: tt.bindingParams, TriggerTemplate: tt.template, } - params, err := ResolveParams(rt, tt.body, map[string][]string{}, tt.extensions) + + params, err := ResolveParams(rt, tt.body, map[string][]string{}, tt.extensions, NewTriggerContext(eventID)) if err != nil { t.Fatalf("ResolveParams() returned unexpected error: %s", err) } @@ -475,6 +489,8 @@ func TestResolveParams(t *testing.T) { } func TestResolveParams_Error(t *testing.T) { + eventID := "1234567" + tests := []struct { name string body []byte @@ -495,7 +511,7 @@ func TestResolveParams_Error(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - params, err := ResolveParams(ResolvedTrigger{BindingParams: tt.bindingParams}, tt.body, map[string][]string{}, tt.extensions) + params, err := ResolveParams(ResolvedTrigger{BindingParams: tt.bindingParams}, tt.body, map[string][]string{}, tt.extensions, NewTriggerContext(eventID)) if err == nil { t.Errorf("did not get expected error - got: %v", params) }