From 5e3fa39bfd4de4e331a3f032f04fba066f266f85 Mon Sep 17 00:00:00 2001 From: Vaibhav Date: Wed, 1 Apr 2020 08:02:44 -0400 Subject: [PATCH] feat: added label and field selectors for resource gateway (#571) --- api/event-source.html | 71 ++++++++- api/event-source.md | 136 +++++++++++++++++- api/gateway.html | 2 +- api/gateway.md | 3 +- api/sensor.html | 2 +- api/sensor.md | 3 +- gateways/server/resource/start.go | 30 ++-- gateways/server/resource/validate.go | 25 ++++ pkg/apis/eventsources/v1alpha1/types.go | 17 ++- .../v1alpha1/zz_generated.deepcopy.go | 28 ++-- 10 files changed, 286 insertions(+), 31 deletions(-) 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 @@

AzureEventsHubEventSourc +(Optional)

Namespace refers to Kubernetes namespace which is used to retrieve the shared access key and name from.

@@ -315,6 +316,7 @@

EmitterEventSource +(Optional)

Namespace to use to retrieve the channel key and optional username/password

@@ -1025,6 +1027,7 @@

GithubEventSource +(Optional)

Namespace refers to Kubernetes namespace which is used to retrieve webhook secret and api token from.

@@ -1137,6 +1140,7 @@

GitlabEventSource +(Optional)

Namespace refers to Kubernetes namespace which is used to retrieve access token from.

@@ -1327,6 +1331,7 @@

HDFSEventSource +(Optional)

Namespace refers to Kubernetes namespace which is used to retrieve cache secret and ket tab secret from.

@@ -1899,7 +1904,9 @@

ResourceFilter labels
-map[string]string + +[]Selector + @@ -1910,7 +1917,9 @@

ResourceFilter fields
-map[string]string + +[]Selector + @@ -2162,6 +2171,61 @@

SQSEventSource +

Selector +

+

+(Appears on: +ResourceFilter) +

+

+

Selector represents conditional operation to select K8s objects.

+

+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+key
+ +string + +
+

Key name

+
+operation
+ +string + +
+(Optional) +

Supported operations like ==, !=, <=, >= etc. +Defaults to ==. +Refer https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors for more info.

+
+value
+ +string + +
+

Value

+

SlackEventSource

@@ -2224,6 +2288,7 @@

SlackEventSource +(Optional)

Namespace refers to Kubernetes namespace which is used to retrieve token and signing secret from.

@@ -2409,5 +2474,5 @@

StripeEventSource

Generated with gen-crd-api-reference-docs -on git commit 1782e0f. +on git commit 739f169.

diff --git a/api/event-source.md b/api/event-source.md index 6d36edc37d..570adca306 100644 --- a/api/event-source.md +++ b/api/event-source.md @@ -359,6 +359,8 @@ Event Hub path/name +(Optional) +

Namespace refers to Kubernetes namespace which is used to retrieve the @@ -653,6 +655,8 @@ ChannelName refers to the channel name +(Optional) +

Namespace to use to retrieve the channel key and optional @@ -2009,6 +2013,8 @@ GitHub upload URL (for GitHub Enterprise) +(Optional) +

Namespace refers to Kubernetes namespace which is used to retrieve @@ -2232,6 +2238,8 @@ GitlabBaseURL is the base URL for API requests to a custom endpoint +(Optional) +

Namespace refers to Kubernetes namespace which is used to retrieve @@ -2585,6 +2593,8 @@ must be set if either ccache or keytab is used. +(Optional) +

Namespace refers to Kubernetes namespace which is used to retrieve cache @@ -3764,7 +3774,8 @@ Description -labels
map\[string\]string +labels
+\[\]Selector @@ -3780,7 +3791,8 @@ Description -fields
map\[string\]string +fields
+\[\]Selector @@ -4263,6 +4275,121 @@ monitor +

+ +Selector + +

+ +

+ +(Appears on: +ResourceFilter) + +

+ +

+ +

+ +Selector represents conditional operation to select K8s objects. + +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +Field + + + +Description + +
+ +key
string + +
+ +

+ +Key name + +

+ +
+ +operation
string + +
+ +(Optional) + +

+ +Supported operations like ==, \!=, \<=, \>= etc. Defaults to ==. Refer +https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\#label-selectors +for more info. + +

+ +
+ +value
string + +
+ +

+ +Value + +

+ +
+

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