Skip to content

Commit

Permalink
Allow trigger eventID to be used as input to triggerbinding
Browse files Browse the repository at this point in the history
Resolves #1427

Adds TriggerContext object to template package to allow future additions to this data if other inputs are desired.
  • Loading branch information
jmcshane committed Sep 27, 2022
1 parent db87102 commit 3445066
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 13 deletions.
2 changes: 1 addition & 1 deletion cmd/binding-eval/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/triggerrun/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions docs/triggerbindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion pkg/sink/sink.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 16 additions & 5 deletions pkg/template/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -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 {
Expand All @@ -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)
}
Expand Down
26 changes: 21 additions & 5 deletions pkg/template/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ func toString(rawMessages []json.RawMessage) []string {
}

func TestApplyEventValuesMergeInDefaultParams(t *testing.T) {
context := TriggerContext{
EventID: "1234567",
}
var (
oneDefault = "onedefault"
twoDefault = "twodefault"
Expand Down Expand Up @@ -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())
}
Expand All @@ -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
Expand Down Expand Up @@ -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)
}
Expand All @@ -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
Expand Down Expand Up @@ -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)
}
Expand All @@ -350,6 +359,8 @@ func TestApplyEventValuesToParams_Error(t *testing.T) {
}

func TestResolveParams(t *testing.T) {
eventID := "1234567"

tests := []struct {
name string
bindingParams []triggersv1.Param
Expand Down Expand Up @@ -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"},
},
}}

Expand All @@ -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)
}
Expand All @@ -475,6 +489,8 @@ func TestResolveParams(t *testing.T) {
}

func TestResolveParams_Error(t *testing.T) {
eventID := "1234567"

tests := []struct {
name string
body []byte
Expand All @@ -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)
}
Expand Down

0 comments on commit 3445066

Please sign in to comment.