diff --git a/api/event-source.html b/api/event-source.html
index 35bc81c321..23087ba95c 100644
--- a/api/event-source.html
+++ b/api/event-source.html
@@ -174,6 +174,7 @@
SlackEventSource
@@ -4386,6 +4513,8 @@ Webhook holds configuration for a REST endpoint
+(Optional)
+
Namespace refers to Kubernetes namespace which is used to retrieve token
@@ -4774,5 +4903,6 @@ all types of events will be processed. More info at
Generated with gen-crd-api-reference-docs on git
-commit 1782e0f .
+commit 739f169 .
+
diff --git a/api/gateway.html b/api/gateway.html
index a82f0300f2..f558530ed0 100644
--- a/api/gateway.html
+++ b/api/gateway.html
@@ -671,5 +671,5 @@ Subscribers
Generated with gen-crd-api-reference-docs
-on git commit 1782e0f .
+on git commit 739f169 .
diff --git a/api/gateway.md b/api/gateway.md
index 5f91474494..a176d36432 100644
--- a/api/gateway.md
+++ b/api/gateway.md
@@ -1321,5 +1321,6 @@ NATS refers to the subscribers over NATS protocol.
Generated with gen-crd-api-reference-docs on git
-commit 1782e0f .
+commit 739f169 .
+
diff --git a/api/sensor.html b/api/sensor.html
index 066f5e044f..94567110a8 100644
--- a/api/sensor.html
+++ b/api/sensor.html
@@ -3131,5 +3131,5 @@ URLArtifact
Generated with gen-crd-api-reference-docs
-on git commit 1782e0f .
+on git commit 739f169 .
diff --git a/api/sensor.md b/api/sensor.md
index 3a124f7f78..d204500f1e 100644
--- a/api/sensor.md
+++ b/api/sensor.md
@@ -6239,5 +6239,6 @@ VerifyCert decides whether the connection is secure or not
Generated with gen-crd-api-reference-docs on git
-commit 1782e0f .
+commit 739f169 .
+
diff --git a/gateways/server/resource/start.go b/gateways/server/resource/start.go
index a8f50e2567..88bca21c35 100644
--- a/gateways/server/resource/start.go
+++ b/gateways/server/resource/start.go
@@ -218,8 +218,12 @@ func (listener *EventListener) listenEvents(eventSource *gateways.EventSource, c
}
// LabelReq returns label requirements
-func LabelReq(key, value string) (*labels.Requirement, error) {
- req, err := labels.NewRequirement(key, selection.Equals, []string{value})
+func LabelReq(sel v1alpha1.Selector) (*labels.Requirement, error) {
+ op := selection.Equals
+ if sel.Operation != "" {
+ op = selection.Operator(sel.Operation)
+ }
+ req, err := labels.NewRequirement(sel.Key, op, []string{sel.Value})
if err != nil {
return nil, err
}
@@ -227,10 +231,10 @@ func LabelReq(key, value string) (*labels.Requirement, error) {
}
// LabelSelector returns label selector for resource filtering
-func LabelSelector(resourceLabels map[string]string) (labels.Selector, error) {
+func LabelSelector(selectors []v1alpha1.Selector) (labels.Selector, error) {
var labelRequirements []labels.Requirement
- for key, value := range resourceLabels {
- req, err := LabelReq(key, value)
+ for _, sel := range selectors {
+ req, err := LabelReq(sel)
if err != nil {
return nil, err
}
@@ -240,16 +244,20 @@ func LabelSelector(resourceLabels map[string]string) (labels.Selector, error) {
}
// FieldSelector returns field selector for resource filtering
-func FieldSelector(fieldSelectors map[string]string) (fields.Selector, error) {
- var selectors []fields.Selector
- for key, value := range fieldSelectors {
- selector, err := fields.ParseSelector(fmt.Sprintf("%s=%s", key, value))
+func FieldSelector(selectors []v1alpha1.Selector) (fields.Selector, error) {
+ var result []fields.Selector
+ for _, sel := range selectors {
+ op := selection.Equals
+ if sel.Operation != "" {
+ op = selection.Operator(sel.Operation)
+ }
+ selector, err := fields.ParseSelector(fmt.Sprintf("%s%s%s", sel.Key, op, sel.Value))
if err != nil {
return nil, err
}
- selectors = append(selectors, selector)
+ result = append(result, selector)
}
- return fields.AndSelectors(selectors...), nil
+ return fields.AndSelectors(result...), nil
}
// helper method to check if the object passed the user defined filters
diff --git a/gateways/server/resource/validate.go b/gateways/server/resource/validate.go
index 1a0bb5133f..480825b2a3 100644
--- a/gateways/server/resource/validate.go
+++ b/gateways/server/resource/validate.go
@@ -19,6 +19,7 @@ package resource
import (
"context"
"fmt"
+ "k8s.io/apimachinery/pkg/selection"
"github.com/argoproj/argo-events/common"
"github.com/argoproj/argo-events/gateways"
@@ -71,5 +72,29 @@ func validate(eventSource *v1alpha1.ResourceEventSource) error {
if eventSource.EventTypes == nil {
return fmt.Errorf("event types must be specified")
}
+ if eventSource.Filter != nil {
+ if eventSource.Filter.Labels != nil {
+ if err := validateSelectors(eventSource.Filter.Labels); err != nil {
+ return err
+ }
+ }
+ if eventSource.Filter.Fields != nil {
+ if err := validateSelectors(eventSource.Filter.Fields); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func validateSelectors(selectors []v1alpha1.Selector) error {
+ for _, sel := range selectors {
+ if sel.Operation == "" {
+ continue
+ }
+ if selection.Operator(sel.Operation) == "" {
+ return fmt.Errorf("unknown selection operation %s", sel.Operation)
+ }
+ }
return nil
}
diff --git a/pkg/apis/eventsources/v1alpha1/types.go b/pkg/apis/eventsources/v1alpha1/types.go
index a2c638f078..27df1cb292 100644
--- a/pkg/apis/eventsources/v1alpha1/types.go
+++ b/pkg/apis/eventsources/v1alpha1/types.go
@@ -155,13 +155,26 @@ type ResourceFilter struct {
// +optional
Prefix string `json:"prefix,omitempty" protobuf:"bytes,1,opt,name=prefix"`
// +optional
- Labels map[string]string `json:"labels,omitempty" protobuf:"bytes,2,opt,name=labels"`
+ Labels []Selector `json:"labels,omitempty" protobuf:"bytes,2,opt,name=labels"`
// +optional
- Fields map[string]string `json:"fields,omitempty" protobuf:"bytes,3,opt,name=fields"`
+ Fields []Selector `json:"fields,omitempty" protobuf:"bytes,3,opt,name=fields"`
// +optional
CreatedBy metav1.Time `json:"createdBy,omitempty" protobuf:"bytes,4,opt,name=createdBy"`
}
+// Selector represents conditional operation to select K8s objects.
+type Selector struct {
+ // Key name
+ Key string `json:"key" protobuf:"bytes,1,name=key"`
+ // Supported operations like ==, !=, <=, >= etc.
+ // Defaults to ==.
+ // Refer https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors for more info.
+ // +optional
+ Operation string `json:"operation,omitempty" protobuf:"bytes,2,opt,name=operation"`
+ // Value
+ Value string `json:"value" protobuf:"bytes,3,name=value"`
+}
+
// AMQPEventSource refers to an event-source for AMQP stream events
type AMQPEventSource struct {
// URL for rabbitmq service
diff --git a/pkg/apis/eventsources/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/eventsources/v1alpha1/zz_generated.deepcopy.go
index ad5630492c..51c9615de0 100644
--- a/pkg/apis/eventsources/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/eventsources/v1alpha1/zz_generated.deepcopy.go
@@ -687,17 +687,13 @@ func (in *ResourceFilter) DeepCopyInto(out *ResourceFilter) {
*out = *in
if in.Labels != nil {
in, out := &in.Labels, &out.Labels
- *out = make(map[string]string, len(*in))
- for key, val := range *in {
- (*out)[key] = val
- }
+ *out = make([]Selector, len(*in))
+ copy(*out, *in)
}
if in.Fields != nil {
in, out := &in.Fields, &out.Fields
- *out = make(map[string]string, len(*in))
- for key, val := range *in {
- (*out)[key] = val
- }
+ *out = make([]Selector, len(*in))
+ copy(*out, *in)
}
in.CreatedBy.DeepCopyInto(&out.CreatedBy)
return
@@ -770,6 +766,22 @@ func (in *SQSEventSource) DeepCopy() *SQSEventSource {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Selector) DeepCopyInto(out *Selector) {
+ *out = *in
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Selector.
+func (in *Selector) DeepCopy() *Selector {
+ if in == nil {
+ return nil
+ }
+ out := new(Selector)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SlackEventSource) DeepCopyInto(out *SlackEventSource) {
*out = *in
|