From 1d51b87bd54682f26100ab622e04bc30cdb31d97 Mon Sep 17 00:00:00 2001 From: Daniel Duvall Date: Sat, 27 Jul 2019 05:47:30 -0700 Subject: [PATCH] Support different trigger parameter operations (#315) (#319) * Support different trigger parameter operations (#315) Implemented an additional `operation` field for trigger parameters that dictates what is to be done with the current value at `dest`. Possible keyword values are: - `overwrite` Overwrite the current value (default/prior behavior) - `prepend` Prepend the value at `dest` with the value at `source.path` - `append` Append the value at `dest` with the value at `source.path` * Specified that `operation` is optional and generated openapi specs --- controllers/sensor/validate.go | 10 +++++ docs/parameterization.md | 3 +- .../complete-trigger-parameterization.yaml | 9 ++++- pkg/apis/sensor/v1alpha1/openapi_generated.go | 7 ++++ pkg/apis/sensor/v1alpha1/types.go | 19 ++++++++++ sensors/trigger-params.go | 19 ++++++++++ sensors/trigger-params_test.go | 38 +++++++++++++++++++ 7 files changed, 103 insertions(+), 2 deletions(-) diff --git a/controllers/sensor/validate.go b/controllers/sensor/validate.go index 5e4089bd70..e313a1e40d 100644 --- a/controllers/sensor/validate.go +++ b/controllers/sensor/validate.go @@ -156,6 +156,16 @@ func validateTriggerParameter(parameter *v1alpha1.TriggerParameter) error { if parameter.Dest == "" { return fmt.Errorf("parameter destination can't be empty") } + + switch op := parameter.Operation; op { + case v1alpha1.TriggerParameterOpAppend: + case v1alpha1.TriggerParameterOpOverwrite: + case v1alpha1.TriggerParameterOpPrepend: + case v1alpha1.TriggerParameterOpNone: + default: + return fmt.Errorf("parameter operation %+v is invalid", op) + } + return nil } diff --git a/docs/parameterization.md b/docs/parameterization.md index 7a30643285..a5d556a0b2 100644 --- a/docs/parameterization.md +++ b/docs/parameterization.md @@ -21,5 +21,6 @@ A `parameter` contains: 1. `src`: 1. `event`: the name of the event dependency 2. `path`: a key within event payload to look for - 3. `value`: default value if sensor can't find `path` in event payload. + 3. `value`: default value if sensor can't find `path` in event payload 2. `dest`: destination key within resource definition whose corresponding value needs to be replaced with value from event payload + 3. `operation`: what to do with the existing value at `dest`, either `overwrite`, `prepend`, or `append` diff --git a/examples/sensors/complete-trigger-parameterization.yaml b/examples/sensors/complete-trigger-parameterization.yaml index 0e85b4206e..b42970aec3 100644 --- a/examples/sensors/complete-trigger-parameterization.yaml +++ b/examples/sensors/complete-trigger-parameterization.yaml @@ -4,6 +4,7 @@ # "name": "trigger-wf-1", # "namespace": "argo-events", # "bucket": "mybucket", +# "port": "9000", # "key": "hello.yaml", # "image": "docker/busybox", # } @@ -48,7 +49,7 @@ spec: bucket: name: THIS_WILL_BE_REPLACED_BUCKET key: THIS_WILL_BE_REPLACED_KEY - endpoint: minio-service.argo-events:9000 + endpoint: "minio-service.argo-events:" insecure: true accessKey: key: accesskey @@ -74,6 +75,12 @@ spec: event: "webhook-gateway:example" path: key dest: source.s3.bucket.key + - src: + event: "webhook-gateway:example" + path: port + dest: source.s3.endpoint + # Append the port to the existing source.s3.endpoint value + operation: append # Apply parameter for workflow resourceParameters: - src: diff --git a/pkg/apis/sensor/v1alpha1/openapi_generated.go b/pkg/apis/sensor/v1alpha1/openapi_generated.go index 796ef86c4a..1e6455906c 100644 --- a/pkg/apis/sensor/v1alpha1/openapi_generated.go +++ b/pkg/apis/sensor/v1alpha1/openapi_generated.go @@ -976,6 +976,13 @@ func schema_pkg_apis_sensor_v1alpha1_TriggerParameter(ref common.ReferenceCallba Format: "", }, }, + "operation": { + SchemaProps: spec.SchemaProps{ + Description: "Operation is what to do with the existing value at Dest, whether to 'prepend', 'overwrite', or 'append' it.", + Type: []string{"string"}, + Format: "", + }, + }, }, Required: []string{"src", "dest"}, }, diff --git a/pkg/apis/sensor/v1alpha1/types.go b/pkg/apis/sensor/v1alpha1/types.go index 313e716f65..7370b28622 100644 --- a/pkg/apis/sensor/v1alpha1/types.go +++ b/pkg/apis/sensor/v1alpha1/types.go @@ -239,6 +239,21 @@ type TriggerCondition struct { All []string `json:"all,omitempty" protobuf:"bytes,2,rep,name=all"` } +// TriggerParameterOperation represents how to set a trigger destination +// resource key +type TriggerParameterOperation string + +const ( + // TriggerParameterOpNone is the zero value of TriggerParameterOperation + TriggerParameterOpNone TriggerParameterOperation = "" + // TriggerParameterOpAppend means append the new value to the existing + TriggerParameterOpAppend TriggerParameterOperation = "append" + // TriggerParameterOpOverwrite means overwrite the existing value with the new + TriggerParameterOpOverwrite TriggerParameterOperation = "overwrite" + // TriggerParameterOpPrepend means prepend the new value to the existing + TriggerParameterOpPrepend TriggerParameterOperation = "prepend" +) + // TriggerParameter indicates a passed parameter to a service template type TriggerParameter struct { // Src contains a source reference to the value of the parameter from a event event @@ -249,6 +264,10 @@ type TriggerParameter struct { // The -1 key can be used to append a value to an existing array. // See https://github.com/tidwall/sjson#path-syntax for more information about how this is used. Dest string `json:"dest" protobuf:"bytes,2,name=dest"` + + // Operation is what to do with the existing value at Dest, whether to + // 'prepend', 'overwrite', or 'append' it. + Operation TriggerParameterOperation `json:"operation,omitempty" protobuf:"bytes,3,opt,name=operation"` } // TriggerParameterSource defines the source for a parameter from a event event diff --git a/sensors/trigger-params.go b/sensors/trigger-params.go index ffeaec0140..c2968a5d97 100644 --- a/sensors/trigger-params.go +++ b/sensors/trigger-params.go @@ -33,6 +33,25 @@ func applyParams(jsonObj []byte, params []v1alpha1.TriggerParameter, events map[ if err != nil { return nil, err } + + switch op := param.Operation; op { + case v1alpha1.TriggerParameterOpAppend, v1alpha1.TriggerParameterOpPrepend: + // prepend or append the current value + current := gjson.GetBytes(jsonObj, param.Dest) + + if current.Exists() { + if op == v1alpha1.TriggerParameterOpAppend { + v = current.String() + v + } else { + v = v + current.String() + } + } + case v1alpha1.TriggerParameterOpOverwrite, v1alpha1.TriggerParameterOpNone: + // simply overwrite the current value with the new one + default: + return nil, fmt.Errorf("unsupported trigger parameter operation: %+v", op) + } + // now let's set the value tmp, err := sjson.SetBytes(jsonObj, param.Dest, v) if err != nil { diff --git a/sensors/trigger-params_test.go b/sensors/trigger-params_test.go index c67fc27f97..36e70a95fb 100644 --- a/sensors/trigger-params_test.go +++ b/sensors/trigger-params_test.go @@ -140,6 +140,44 @@ func Test_applyParams(t *testing.T) { want: []byte(`{"x":"magaldi"}`), wantErr: false, }, + { + name: "simpleJSON (prepended field) -> success", + args: args{ + jsonObj: []byte(`{"x":"before"}`), + params: []v1alpha1.TriggerParameter{ + { + Src: &v1alpha1.TriggerParameterSource{ + Event: "simpleJSON", + Path: "name.last", + }, + Dest: "x", + Operation: v1alpha1.TriggerParameterOpPrepend, + }, + }, + events: events, + }, + want: []byte(`{"x":"magaldibefore"}`), + wantErr: false, + }, + { + name: "simpleJSON (appended field) -> success", + args: args{ + jsonObj: []byte(`{"x":"before"}`), + params: []v1alpha1.TriggerParameter{ + { + Src: &v1alpha1.TriggerParameterSource{ + Event: "simpleJSON", + Path: "name.last", + }, + Dest: "x", + Operation: v1alpha1.TriggerParameterOpAppend, + }, + }, + events: events, + }, + want: []byte(`{"x":"beforemagaldi"}`), + wantErr: false, + }, { name: "non JSON, no default -> pass payload bytes without converting", args: args{